背景
假设我正在尝试保留大量项目,使用Web UI提供添加新项目的可能性。 我的架构是一个Web UI(React / Redux)+一个数据库/服务器(Graph.cool)。
现在当我添加一个新项目时,我可以做的只是运行“创建”查询,获取带有数据库ID的项目,并将项目存储在按ID索引所有项目的对象中。
问题:网络可能很慢/脱机,请求可能会失败,我仍然希望能够立即向用户显示列表中新创建的项目,并稍后与数据库同步。
问题
我需要一个允许我首先在本地创建项目的解决方案,然后在响应返回时将本地ID替换为数据库ID。 我怎么能这样做?
答案 0 :(得分:1)
最简单的方法是在对象上创建某种localKey
字段,并按照惯例将其添加到商店。
每当后端完成处理并且事件进入时,不是将新对象添加到商店,而是使用localKey
查找本地副本,并替换它。
答案 1 :(得分:0)
原来这是我所拥有的代码组织/ Redux的问题。
我无法弄清楚如何实施Tobe O建议的某种解决方案,因为:
我所做的事情似乎运作良好,是:
这是我的代码解决方案,Redux + Sagas + Kea +经典的待办事项列表示例:
export default kea({
path: () => ["kea", "taskStore"],
actions: () => ({
addTask: title => ({ title }),
storeLocalTask: (localId, title) => ({ localId, title }),
storeDBTask: (localId, task) => ({ localId, task }),
setTasks: tasks => ({ tasks }),
fetchTasks: () => ({})
}),
*start() {
const { fetchTasks } = this.actions;
yield put(fetchTasks());
},
reducers: ({ actions }) => ({
indexedTasks: [
{},
PropTypes.object,
{
[actions.setTasks]: (state, payload) => indexById(payload.tasks),
[actions.storeLocalTask]: (state, payload) => {
const { localId, title } = payload;
return { ...state, [localId]: { localId, title } };
},
[actions.storeDBTask]: (state, payload) => {
const { localId, task } = payload;
const { [localId]: _dispose_, ...rest } = state;
return { ...rest, [task.id]: task };
}
}
]
}),
takeLatest: ({ actions, workers }) => ({
[actions.fetchTasks]: workers.fetchTasks,
[actions.addTask]: workers.createTask
}),
workers: {
*fetchTasks() {
const res = yield db.query({
query: gql`
query {
allTasks {
id
title
}
}
`
});
const { setTasks } = this.actions;
yield put(setTasks(res.data.allTasks));
yield delay(1000);
},
*createTask(action) {
const { storeLocalTask, storeDBTask } = this.actions;
const { title } = action.payload;
const localId = randomString();
yield put(storeLocalTask(localId, title));
const res = yield db.mutate({
mutation: gql`
mutation($title: String!) {
createTask(title: $title) {
id
title
}
}
`,
variables: { ...action.payload }
});
yield put(storeDBTask(localId, res.data.createTask));
yield delay(1000);
}
}
});