【问题标题】:Redux saga - error binding - appropriate way to bind error to local stateRedux saga - 错误绑定 - 将错误绑定到本地状态的适当方法
【发布时间】:2023-03-14 05:42:01
【问题描述】:

我们有一个使用 redux-saga 的 ReactJS 应用程序。 在 redux-saga 我们执行所有的数据抓取(http webrequests)。 此外:我们使用 React 钩子。

场景:

我们有一个向 redux 发送动作的按钮。 Redux-saga 处理这个动作并触发一个 webrequest。

现在,此网络请求失败(例如服务器已关闭)。

我们现在要做的是更改按钮的文本。 所以实际上,我们想回到动作被分派的“范围”。

问题:

从 redux-saga 回到按钮的适当方法是什么?

我找到了这个:

https://github.com/ricardocanelas/redux-saga-promise-example

这是否适合在 2021 年与钩子一起使用?

【问题讨论】:

    标签: reactjs react-hooks redux-saga


    【解决方案1】:

    你发布的那个例子听起来不必要地令人费解。使用 redux-sagas 处理错误可以相对简单。我们将考虑应用程序的 3 个部分 - UI、商店和动作/saga 链。

    用户界面:

    const SomeUIThing = () => {
    
      const callError = useSelector(state => state.somewhere.error);
      const dispatch = useDispatch();
    
      return (
        <button onClick={
          dispatch({
            type: "API_CALL_REQUEST"
          })
        }>
          {callError ? 'There was an error' : 'Click Me!'}
        </button>
      )
    }
    

    您可以看到 UI 正在从商店中读取。单击时,它将向商店发送和API_CALL_REQUEST 操作。如果商店中记录了错误,它将有条件地呈现文本的按钮,这正是您想要的。

    商店

    您需要一些操作和减速器才能在商店中创建或清除错误。所以最初的商店可能是这样的:

    const initialState = {
      somewhere: {
        error: undefined,
        data: undefined
      }
    }
    
    function reducer(state = initialState, action){
      switch(action.type){
        case "API_CALL_SUCCESS":
          return {
            ...state,
            somewhere: {
              ...state.somewhere,
              data: action.payload
            }
          }
        case "API_CALL_FAILURE":
          return {
            ...state,
            somewhere: {
              ...state.somewhere,
              error: action.payload
            }
          }
        case "CLEAR":
          return {
            ...state,
            somewhere: initialState.somewhere
          }
        default:
          return state;
      }
    }
    

    现在你的 reducer 和你的 store 可以处理一些基本的 api 调用响应,包括失败和成功。现在让 sagas 处理 api 调用逻辑流程

    传奇

    function* handleApiCall(){
      try {
    
        // Make your api call:
        const response = yield call(fetch, "your/api/route");
    
        // If it succeeds, put the response data in the store
        yield put({ type: "API_CALL_SUCCESS", payload: response });
    
      } catch (e) {
    
        // If there are any failures, put them in the store as an error
        yield put({ type: "API_CALL_ERROR", payload: e })
    
      }
    }
    
    function* watchHandleApiCall(){
      yield takeEvery("API_CALL_REQUEST", handleApiCall)
    }
    

    最后一部分是处理 api 调用的地方。当您单击 UI 中的按钮时,watchHandleApiCall 会侦听从按钮单击发出的 API_CALL_REQUEST。然后它会触发handleApiCall saga,从而进行调用。如果调用成功,则从 to store 触发成功操作。如果失败,或者有任何错误,则会向 store 触发错误操作。然后,UI 可以从存储中读取任何错误值并做出相应的反应。

    如您所见,使用 try/catch 块,在 sagas 中处理错误非常简单,只要您设置了存储来保存错误。

    【讨论】:

    • 非常感谢,我已接受您的回答。还有一个问题:如果使用 takeLatest 而不是 takeEvery ,这种方法是否也有效?
    • 好吧。 takeLatest 将简单地取消当前正在进行的所有先前调用(例如,如果用户快速单击按钮多次)。最终,它将只是将使用的最新调度操作
    猜你喜欢
    • 2017-11-06
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 2016-07-05
    • 2016-02-07
    相关资源
    最近更新 更多