Redux如何在reducer中处理错误

9
我不确定如何在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 
 });

components/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 新手,因此在应用程序结构方面需要任何帮助,将不胜感激!

1个回答

9

一般的模式是返回一个表示发生错误的状态。例如,在 TODO 应用程序的上下文中,如果接收到的操作不正确,则可以使用以下内容:

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逻辑中,您声明了与接收的操作相对应的状态行为。与外部世界/上下文没有关系(该函数被认为是纯的)。抛出错误或调用外部内容会破坏模式。

有趣的是,您可以有一个中间件来查看具有非空错误键的状态并采取措施。

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

您可以在源代码中看到,redux不会执行任何操作。它只是重新设置为其notDispatching状态。因此,如果您没有改变状态,则一切仍然良好(尽管可能性有限)。如果您做了更改,则手头就有了一个不一致的状态...


如果错误是预期的,你可能想要使用一个thunk或其他方法。例如,如果有效载荷包括必须检查的用户输入。如果错误不是预期的,例如当您检查状态可能因某些并发操作而处于不正确状态时,我认为抛出异常是可以接受的。可以在应用程序顶层捕获错误以显示错误弹出窗口或其他内容。 - Eric Burel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接