以下是调度错误/成功消息的标准方法,至少是教程推荐的内容:
{ 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: { ... } }
但是,我遇到的问题是,这些错误/成功消息会显示在 EVERY 组件内部,并会监听特定的减速器处理这些操作。
示例方案:
图片您有一个 todo 应用程序,其中有三个操作添加,编辑和删除但是这三个操作都是这些操作是根据UI从单独的页面执行的。并且它们全部由相同的 todo reducer 处理。
此外,所有提供用于触发这些操作的UI的组件都会通过 mapStateToProps 收听此 todo reducer 以接收 todo更改 (与此示例无关)和成功&错误消息:
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>}
以上问题 问题是无法区分 添加待办事项错误,编辑待办事项错误和删除待办事项错误。
因此,如果添加待办事项会触发错误,此错误现在也会显示在编辑待办事项和删除待办事项旁边,因为所有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...
});
然后,您只需在组件中侦听这些成功/错误消息,然后按以下方式呈现这些消息:
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>}
等...
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>}
这样做的缺点是它会迫使你为应用程序提供的每个动作创建一个子减速器,我不确定这是一个正确的方法吗?
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 }
然后,您只需在组件中侦听这些成功/错误消息,然后按以下方式呈现这些消息:
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>}
等...
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>}
这样做的缺点是你必须确保给定减速器内的每个错误/成功 键 本地唯一强烈的>减速器内部。
它还会使 stateMapToProps 中的键更加详细,而不是说state.todo.error
您必须引用error
通过使用您提供的特定名称。
所以我的问题是,基于上述所有情况,我在上述观察中完全错过了某些方面,或者我的观察是否正确,在哪种情况下达到预期结果的标准方法是什么?
我提出的两种解决方案对于现实世界的应用程序是合法的还是过于幼稚的?
非常感谢!
答案 0 :(得分:3)
您的第一个选项存在问题,因为每个子减速器都无法访问全局状态(待办事项列表)。我想知道你如何编写每个子减速器......
你的第二个选择相对较好。但是,它会显示一个常见的红色标记:当您开始命名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"}
}
}
所以这就是我修复代码的方式。但是,这对我来说似乎有点矫枉过正,因为这种状态允许您表示并存储来自不同缩减器的同时错误的任何组合,这对于向用户显示并非易事。
在错误显示的情况下,很少需要这样的精度,并且通常在操作失败时强制触发弹出窗口或烤面包机消息。
此外,您应该查看redux-actions
和redux-promise-middleware
,这就是我处理错误的方法。