React Redux正确处理每个组件特有的错误/成功消息的方法

lin*_*new 8 reactjs redux react-redux

问题大纲

下面是调度错误/成功消息的标准方法,至少是教程推荐的内容:

{ type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
{ type: 'FETCH_POSTS_SUCCESS', success: 'yay', response: { ... } }

{ type: 'FETCH_POSTS', status: 'error', error: 'Oops' }
{ type: 'FETCH_POSTS', status: 'success', response: { ... } }
Run Code Online (Sandbox Code Playgroud)

但是,我遇到的问题是,这些错误/成功消息将显示在每个组件内部,监听正在处理这些操作的特定reducer.

示例场景:

图像你有一个todo应用程序有三个动作添加,编辑和删除,但所有这三个动作都是从UI的单独页面执行.它们都由相同的todo减速机处理.

此外,提供触发这些操作的UI的所有组件都通过mapStateToProps监听此todo reducer以接收待办事项更改(在此示例中不相关)以及成功和错误消息:

function mapStateToProps(state) {
    return { 
        success: state.todo.success,
        error: state.todo.error,
    }; 
}

{!!this.props.success && <p>{this.props.success}</p>}
{!!this.props.error && <p>{this.props.error}</p>}
Run Code Online (Sandbox Code Playgroud)

问题与上面 的问题是,有没有办法区分之间添加待办事项错误,编辑待办事项错误和删除待办事项错误.

因此,如果 添加todo触发错误,此错误现在也会显示在编辑待办事项和删除待办事项旁边,因为所有3个操作都在侦听相同的内容:state.todo.error.

以下是我提出的2个解决方案.任何反馈/批评以及新建议都将受到欢迎.


到目前为止我想出了什么

1:处理每个操作的错误/成功的全局状态缩减器

设置一个处理每个操作的错误/成功的全局状态缩减器 - reducer上的键将由每个操作独有的小型专用子缩减器组成,即:

const status = combineReducers({
  add_todo,     // handles error/success for add_todo
  edit_todo,    // handles error/success for edit_todo
  delete_todo,  // handles error/success for delete_todo
  …
  update_bio,   // handles error/success for update_bio
  etc...
});
Run Code Online (Sandbox Code Playgroud)

然后,您只需在组件中侦听这些成功/错误消息,然后按如下方式呈现它们:

function mapStateToProps(state) {
    return { 
        error: state.status.add_todo.error,
        success: state.status.add_todo.success
    }; 
}

{!!this.props.error && <p>{this.props.error}</p>}
{!!this.props.success && <p>{this.props.success}</p>}
Run Code Online (Sandbox Code Playgroud)

等等...

function mapStateToProps(state) {
    return { 
        error: state.status.edit_todo.error,
        success: state.status.edit_todo.success
    }; 
}

{!!this.props.error && <p>{this.props.error}</p>}
{!!this.props.success && <p>{this.props.success}</p>}
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是它会强制你为应用程序提供的每个动作创建一个子减速器,我不确定这是一个正确的方法吗?


2:在管理多个操作的每个reducer内部使用本地唯一的错误/成功键

即我们可以修改todo reducer如下:

ADD_TODO_FAILED:
    return {...state, error_add_todo: action.error }

EDIT_TODO_FAILED:
    return {...state, error_edit_todo: action.error }

DELETE_TODO_FAILED:
    return {...state, error_delete_todo: action.error }
Run Code Online (Sandbox Code Playgroud)

然后,您只需在组件中侦听这些成功/错误消息,然后按如下方式呈现它们:

function mapStateToProps(state) {
    return { 
        error: state.todo.error_add_todo,
        success: state.todo.success_add_todo
    }; 
}

{!!this.props.error && <p>{this.props.error}</p>}
{!!this.props.success && <p>{this.props.success}</p>}
Run Code Online (Sandbox Code Playgroud)

等等...

function mapStateToProps(state) {
    return { 
        error: state.todo.error_edit_todo,
        success: state.todo.success_edit_todo
    }; 
}

{!!this.props.error && <p>{this.props.error}</p>}
{!!this.props.success && <p>{this.props.success}</p>}
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是你必须确保给定reducer 中的每个错误/成功 键在该reducer 内部是唯一的.

而且这也会使指键内stateMapToProps更详细的,而不是说state.todo.error你就不得不提及的是error通过使用你给它的具体名称.

题

所以我的问题是,基于上述所有情况,我在上述观察中完全错过了某些方面,或者我的观察是否正确,在哪种情况下达到预期结果的标准方法是什么?

我提出的两种解决方案对于现实世界的应用程序是合法的还是过于幼稚的?

非常感谢!

Vin*_*ier 3

1.

您的第一个选择是有问题的,因为您的每个子减速器都无法访问全局状态(待办事项列表)。我想知道你如何编码每个子减速器......

2.

你的第二个选择相对较好。然而,它显示了一个常见的危险信号:当您开始命名诸如state.todo.error_add_todo和 之类的变量时state.todo.error_edit_todo,您通常应该使用一个对象来代替,以 结尾state.todo.error.add_todo。

事实上,我什至会更进一步,分组error并success进入status。

这意味着您将重塑您的状态以具有以下形状:

{
  todos:[{...todo1}, {...todo2}, ...todos]
  status:{
    add_todo: {success: true, error: false, message: "yay"}
    remove_todo: {success: false, error: true, message: "nooo"}
  }
}
Run Code Online (Sandbox Code Playgroud)

所以这就是我修复你的代码的方式。然而,这对我来说似乎有点矫枉过正,因为这种状态形状允许您表示和存储来自不同减速器的同时错误的任意组合,这对于向用户显示来说并不简单。

在错误显示的情况下,很少需要这种精度,而且通常情况下,当操作失败时,您只是强制触发弹出窗口或烤面包机消息。

另外,您可能应该看看redux-actions和redux-promise-middleware,这就是我处理错误的方式。

  • 感谢您的见解,就选项 1 而言,子减速器不需要访问 todos 的全局状态,它们将仅致力于错误/成功消息,然后您可以通过 mapStateToProps 即状态收听这些消息.status.addTodo.error,state.status.addTodo.success (2认同)