Search code examples
reactjsreduxredux-thunkredux-saga

how to setstate after saga async request


I'm using redux-saga in my project. I used redux-thunk before, so i can't setState ends of some async request. like

this.props.thunkAsync()
  .then(){
    this.setState({ '' });
  }

Since thunk returns promise, i could use 'then'. But i can't do this with saga, because saga doesn't return promise. So i did it in componentWillReceiveProps by checking flag props (like REQUEST_SUCCESS,REQUEST_WAITING...) has been changed. I think it's not good way to solve this problem.

So.. My question is how can i do some works when async request ends in redux-saga!


Solution

  • Every api call you make is processed as an async request but handled using a generator function in a saga.

    So, After a successful api call, you can do the following possible things.

    1. Make another api call like
    function* onLogin(action) {
      try {
        const { userName, password } = action;
        const response = yield call(LoginService.login, userName, password);
        yield put(LoginService.loginSuccess(response.user.id));
        const branchDetails = yield call(ProfileService.fetchBranchDetails, response.user.user_type_id);
        yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails));
      } catch (error) {
        yield put(ProfileActions.fetchUserDetailsError(error));
      }
    }
    
    1. Pass a Callback after successfull api

      onLoginClick() {
        const { userName, password } = this.state;
        this.props.login(userName, password, this.onLoginSuccess);
      }
      
      onLoginSuccess(userDetails) {
        this.setState({ userDetails });
      }
      
      function *onLogin(action) {
        try {
           const { userName, password, onLoginSuccess } = action;
           const response = yield call(LoginService.login, userName, password);
           if (onLoginSuccess) {
               onLoginSuccess(response);
           }
      
           yield put(LoginService.loginSuccess(response.user.id));
           const branchDetails = yield call(ProfileService.fetchBranchDetails, 
           response.user.user_type_id);
           yield put(ProfileActions.fetchBranchDetailsSuccess(branchDetails));
       } catch (error) {
           yield put(ProfileActions.fetchUserDetailsError(error));
       }
      

      }

    2. Update Reducer State and get from props by mapStateToProps

      yield put(LoginService.loginSuccess(response.user.id));        
      @connect(
          state => ({
              usedDetails: state.user.get('usedDetails'),
          })
      )
      static getDerivedStateFromProps(nextProps, prevState) {
          const { usedDetails } = nextProps;
          return {
              usedDetails
          }
      }