【问题标题】:Redux how to handle errors in reducerRedux如何处理reducer中的错误
【发布时间】:2017-06-09 01:08:51
【问题描述】:

我不确定如何处理 redux reducer 中的错误。当我的 API 获取返回数据时,我需要转换其结构并检查已在结果数据上设置的各种属性。但是,我不能在 reducer 中抛出错误,因为 redux 至少需要返回之前的状态。我该如何处理这个?

注意:我使用react-redux-toastr 来处理错误,并且可以访问组件和操作函数中的错误调度程序。

reducers/object-search.js:

case "FETCH_OBJECTS_FULFILLED": {
  // munge data into expected format

  const _allObjects = [];
  const data = action.payload;

  // if can't find the surveys property
  if (!data.hasOwnProperty("surveys")) {

    // - - How do I handle this within the reducer? - - 

    // this.handleAlert("error", "ERROR", " Cannot find a list of surveys. Please contact support.");
    return {
      ...state,
      fetching: false
    }
  }

  // transform data (omitted for brevity's sake)

  return {
    ...state,
    fetching: false,
    fetched: true,
    options: _allObjects,
    surveys: data.surveys.map(survey => survey.name)
    // toastrs: [newToastr, ...state.toastrs]
  };

}

在连接 ObjectSearch 组件后,我确实尝试在 ObjectSearch reducer 中更新 toastr 的 store 切片:

reducers/index.js:

 const rootReducer = combineReducers({
    toastr: toastrReducer,
    ObjectSearch 
 });

组件/object-search.js

@connect(store => {
  return {
     fetching: store.ObjectSearch.fetching,
     fetched: store.ObjectSearch.fetched,
     ready: store.ObjectSearch.ready,
     surveys: store.ObjectSearch.surveys,
     toastrs: store.toastr.toastrs
   };
 })

但是,将以下内容添加到 reducers/object-search.js: 似乎更新了 ObjectSearch.toastrs 而不是 toastr.toastrs :(

  const toastrs = [...state.toastr];
  const newToastr = {
     id: guid(),
     type: 'light',
     title: 'OBJECT SEARCH ERROR',
     message: 'No Data. Please contact support.',
     options: {
       ...REDUX_TOASTR_OPTIONS,
       icon: icons.ERROR_ICON,
       status: 'error'
     }
   };
  toastrs.push(newToastr);

我是一个 react/redux 新手,所以对于应用程序结构的任何帮助将不胜感激!

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    一般模式是返回指示发生错误的状态。例如,在 TODO APP 的上下文中,如果接收到的操作不正确,那么您可以使用以下内容:

    function reducer (state = { todos: [], error: null }, action) {
    
       switch (action.type) {
    
           case "ADD_TODO":
               if (typeof action.todo === "string") {
    
                    return Object.assign({}, state, {
                        error: {
                            code: "INVALID TODO ACTION",
                            message: "The todo action received was empty, need a .text property",
                            action
                        }
                     });
    
               } else {
    
                   return { todos: [action.text, ...state.todos], error: null }
    
               }
    
       }
    
    }
    

    然后,任何收听存储的订阅者在看到返回的新状态后都可以采取行动。

    我认为重要的是一切都是声明性的,在 reducer 逻辑中,您声明状态相对于接收到的操作的行为。与外部世界/上下文无关(据说该功能是纯的)。抛出一个错误,或者调用外部的东西会破坏这种模式。

    有趣的是,您可以让中间件监视具有非空错误键的状态并对此采取措施。

    您可能会担心的另一件事是当您的操作出现真正的错误时:对象的形状是意外的,或者您有一个字符串而不是错误等...在这种情况下,您可能会遇到意外抛出错误。会发生什么?

    你可以在source 中看到 redux 没有做任何事情。它会简单地重置到它的 notDispatching 状态。因此,如果您没有改变状态,一切都还可以(无论如何都可以)。如果你这样做了,那么你手上就会有一个不稳定的状态......

    【讨论】:

    • 如果错误是意料之中的,您可能想改用 thunk 或其他什么。例如,如果有效负载包含必须检查的用户输入。如果错误不是预期的,例如当您检查状态可能由于某些并发操作而处于不正确状态时。我觉得扔也行。可以在应用顶层捕获错误以显示错误弹出窗口或其他任何内容。
    猜你喜欢
    • 1970-01-01
    • 2017-05-16
    • 1970-01-01
    • 2017-08-27
    • 2017-04-03
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 2019-06-14
    相关资源
    最近更新 更多