reactjs - React Redux Store Layout:如何处理“添加项目”请求的“待处理”状态?
问题描述
示例商店:
{
todos: {
byId: {
"1": { id: "1", title: "foo" },
"2": { id: "2", title: "bar" }
},
allIds: ["2", "1"] // ordered by `title` property
}
}
现在用户想要添加一个新的 Todo 条目:
dispatch({
type: 'ADD_TODO_REQUEST',
payload: { title: "baz" }
})
这会触发一些 API 请求:POST /todos
. pending
只要没有响应(success
或error
),请求的状态就是。这也意味着,我还没有id
新创建的 Todo 条目。
现在我已经想将它添加到商店(并显示它)。但我当然不能将它添加到byId
and allIds
,因为它还没有id
。
问题 1:我应该如何改变商店的布局才能做到这一点?
响应到达后,有两种可能:
success
: 更新 store 并设置id
新 Todo Entry 的属性。使用dispatch({type:'ADD_TODO_SUCCESS', payload: response.id})
.error
:从商店中删除新的 Todo 条目。使用dispatch({type:'ADD_TODO_ERROR', payload: ???})
现在,这两个动作的 reducer 必须以某种方式在 store 中找到相应的元素。但它没有标识符。
问题2:如果没有,我如何在商店中找到该商品id
?
附加信息:
- 我正在使用 redux-saga 的反应
- 应该可以同时
ADD_TODO_REQUEST
运行多个并发。尽管商店内必须有多个pending
Todo 条目。(例如,如果网络连接很慢,用户只是输入“title1”并点击“add”按钮,然后点击“title2”和“add”,“title3”和“add”。)虽然无法禁用AddTodo
请求挂起时的组件。
您如何在您的应用程序中解决这些问题?
编辑:还有更多:
相同的功能应该可用于“更新”和“删除”待办事项条目:
当用户编辑一个 Todo 条目然后点击“保存”按钮时,该项目也应该处于
pending
状态,直到响应到达。如果是错误,则必须将旧版本的数据放回存储区(无需从服务器请求)。当用户单击“删除”时,该项目将立即消失。但是如果服务器响应是错误的,那么该项目应该被放回列表中。
如果有错误响应,这两个操作都应该恢复以前的数据。
解决方案
我找到了一个简单的解决方案。但我确信还有其他可能性甚至更好的解决方案。
将 Todo 条目保存在 2 个单独的集合中:
{
todos: {
byId: {
"1": { id: "1", title: "foo" },
"2": { id: "2", title: "bar" }
},
allIds: ["2", "1"],
pendingItems: [
{ title: "baz" },
{ title: "42" }
]
}
}
现在我可以“通过引用”在商店中找到它们。
// handle 'ADD_TODO_REQUEST':
const newTodoEntry = { title: action.payload.title };
yield put({ type: 'ADD_TODO_PENDING', payload: newTodoEntry });
try {
const response = yield api.addTodoEntry(newTodoEntry);
yield put({ type: 'ADD_TODO_SUCCESS', payload: { id: response.id, ref: newTodoEntry } });
} catch(error) {
yield put({ type: 'ADD_TODO_ERROR', payload: newTodoEntry });
}
减速器将如下所示:
case 'ADD_TODO_PENDING':
return {
..state,
pendingItems: // add action.payload to this array
}
case 'ADD_TODO_SUCCESS':
const newTodoEntry = { ...action.payload.ref, id: action.payload.id };
return {
..state,
byId: // add newTodoEntry
allByIds: // add newTodoEntry.id
pendingItems: // remove action.payload.ref from this array
}
case 'ADD_TODO_ERROR':
return {
..state,
pendingItems: // remove action.payload.ref from this array
}
有2个问题:
reducer必须使用对象引用。不允许 reducer 从 的动作负载中创建自己的对象
ADD_TODO_PENDING
。Todo Entries 不能在商店中轻松分类,因为有两个不同的集合。
有2个解决方法:
uuid
使用仅在项目处于状态时才存在的客户端生成的 spending
。这样,客户可以轻松地跟踪所有内容。
2.
insertAtIndex
a)为待处理的项目添加某种属性。然后 React 组件代码可以合并这两个集合,并以自定义顺序显示混合数据。b) 只需将物品分开即可。例如,在服务器数据库中已经持久化的项目列表之上和之下的待处理项目列表。
推荐阅读
- javascript - 错误:无法解析 JS 同构应用程序中的“fs”
- spring-boot - 如何将wiremock服务从spring boot应用程序部署到azure app services?
- c# - 如何使用 OpenCV4 在 Unity3d 中修复灰度图像的可视化?
- scala - Scala immutable.Map.apply 每次调用时都会重新评估
- sql - 将 SQL Server 代码转换为 MS Access SQL 代码 - DISTINCT 问题
- c# - 在 C# 中是否可以用值实例化一个类?
- python - 未调用类方法 - Python Tkinter
- python - 通过有序字典搜索
- bootstrap-modal - 使用 TypeScript 自定义确认框
- java - 如何正确更新 Fragment 中的 GraphView 对象(GraphView 未使用传入数据进行更新)