如何在 saga 异步请求后设置状态

god*_*nal 9 reactjs redux redux-thunk redux-saga

我在我的项目中使用 redux-saga。我之前使用过 redux-thunk,所以我不能 setState 结束一些异步请求。喜欢

this.props.thunkAsync()
  .then(){
    this.setState({ '' });
  }
Run Code Online (Sandbox Code Playgroud)

由于 thunk 返回 promise,我可以使用“then”。但我不能用 saga 做到这一点,因为 saga 不返回承诺。因此,我通过检查标志道具(如 REQUEST_SUCCESS、REQUEST_WAITING...)在 componentWillReceiveProps 中进行了更改。我认为这不是解决这个问题的好方法。

所以..我的问题是当异步请求以 redux-saga 结束时我该如何做一些工作!

Vla*_*ost 5

但我不能用 saga 做到这一点,因为 saga 不返回承诺

Redux-saga略有不同,thunk因为它是进程管理器,而不是简单的中间件:thunk仅对触发的动作执行反应,但saga有自己的“进程”(正式回调刻度域)并且可以通过效果对动作进行操作。

以异步用行动履行通常的方式redux-saga是分裂原的行动ACTION_REQUESTACTION_SUCCESSACTION_FAILURE变种。然后 reducer 只接受 SUCCESS/FAILURE 操作,并且可能请求乐观更新

在这种情况下,您的saga流程可能如下所示

function* actionNameSaga(action) {
    try {    
        const info = yield call(fetch, { params: action.params }
        yield put('ACTION_NAME_SUCCESS', info)
    } catch(err) {
        yield put('ACTION_NAME_FAILURE', err)
    }

function* rootSaga() {
    yield takeEvery('ACTION_NAME', actionNameSaga)
}
Run Code Online (Sandbox Code Playgroud)

请记住,yield操作本身与承诺等待无关 - 它只是将异步等待委托给 saga 进程管理器。


Muk*_*han 3

您进行的每个 api 调用都作为异步请求进行处理,但使用传奇中的生成器函数进行处理。

因此,在成功调用 api 后,您可以执行以下操作。

  1. 进行另一个 api 调用,例如
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));
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 成功后传递回调 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));
     }
    
    Run Code Online (Sandbox Code Playgroud)

    }

  2. 更新Reducer State并通过mapStateToProps从props中获取

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