我们可以在 react router 更改时取消 api 响应吗?
Can we cancel out api response when the react router is changed?
我在 redux 中使用相同的表单和相同的状态进行添加和编辑。当我调用 api 获取数据进行编辑时,我们更改路由器以在响应到达之前添加表单。所有表单数据都将自动填充以添加项目,因为我使用相同的状态进行添加和编辑。有什么办法可以防止这种情况发生吗?
我的动作创作者:
fetchById: function (entity, id) {
return function (dispatch) {
dispatch(apiActions.apiRequest(entity));
return (apiUtil.fetchById(entity, id).then(function (response) {
dispatch(apiActions.apiResponse(entity));
dispatch(actions.selectItem(entity, response.body));
}
}
}
由于响应较晚,因此 selectItem 发送较晚。当我打开添加项目的表单时,此表单会填入来自响应的数据。
前几天我看到了这个 blog post,我认为第二部分描述了您要查找的内容。您不一定要取消请求但忽略响应。
基本上你想创建一个外部减速器,它会跟踪你对具有唯一 ID 的服务器的异步请求。只有当请求 id 在列表中时才允许它进入子减速器。
当您切换页面时,您需要清除此唯一 ID 列表。
直接从博客中提取:
const initialState = [];
function update(state = initialState, action) {
const { seqId } = action;
if (action.type === constants.UNLOAD) {
return initialState;
}
else if (seqId) {
let newState;
if (action.status === 'start') {
newState = [...state, seqId];
}
else if (action.status === 'error' || action.status === 'done') {
newState = state.filter(id => id !== seqId);
}
return newState;
}
return state;
}
然后限制子减速器:
let store = createStore((state, action) => {
if (action.seqId &&
(action.status === 'done' || action.status === 'error') &&
state &&
state.asyncRequests.indexOf(action.seqId) === -1) {
return state;
}
return reducer(state, action);
});
为此向詹姆斯大声喊叫。非常好的解决方案,在他的博客 post.
中有很好的解释
Thunk 将 dispatch
和 getState
作为参数。
如果您将当前路线保留在您所在州的某处,您可以在 API 回调中检查您是否仍在与 getState().routing.path
或类似的页面上,并且 return
如果自 API 调用开始后它发生了变化。
如果您不保持当前路线处于状态,您可以改为阅读this.context.router
in your component (don’t forget to define contextTypes
to get it!) and pass it to the action creator. The action creator can then use router.isActive()
来检查请求前后我们是否仍在同一路径上。
最后,您可以不使用相同的状态来编辑和添加项目。你的状态形状可以看起来像 { drafts: { newItem: ..., 1: ..., 2: ... } }
,你可以在 drafts.newItem
中保留“添加”表单,并通过相应实体的 ID 保留任何“编辑”表单。这样他们就永远不会互相覆盖,并且作为奖励,可以保留正在进行的编辑,例如如果您按“返回”然后再次转到表单(当然取决于您是否希望在您的用户体验中使用它)。
我在 redux 中使用相同的表单和相同的状态进行添加和编辑。当我调用 api 获取数据进行编辑时,我们更改路由器以在响应到达之前添加表单。所有表单数据都将自动填充以添加项目,因为我使用相同的状态进行添加和编辑。有什么办法可以防止这种情况发生吗?
我的动作创作者:
fetchById: function (entity, id) {
return function (dispatch) {
dispatch(apiActions.apiRequest(entity));
return (apiUtil.fetchById(entity, id).then(function (response) {
dispatch(apiActions.apiResponse(entity));
dispatch(actions.selectItem(entity, response.body));
}
}
}
由于响应较晚,因此 selectItem 发送较晚。当我打开添加项目的表单时,此表单会填入来自响应的数据。
前几天我看到了这个 blog post,我认为第二部分描述了您要查找的内容。您不一定要取消请求但忽略响应。
基本上你想创建一个外部减速器,它会跟踪你对具有唯一 ID 的服务器的异步请求。只有当请求 id 在列表中时才允许它进入子减速器。
当您切换页面时,您需要清除此唯一 ID 列表。
直接从博客中提取:
const initialState = [];
function update(state = initialState, action) {
const { seqId } = action;
if (action.type === constants.UNLOAD) {
return initialState;
}
else if (seqId) {
let newState;
if (action.status === 'start') {
newState = [...state, seqId];
}
else if (action.status === 'error' || action.status === 'done') {
newState = state.filter(id => id !== seqId);
}
return newState;
}
return state;
}
然后限制子减速器:
let store = createStore((state, action) => {
if (action.seqId &&
(action.status === 'done' || action.status === 'error') &&
state &&
state.asyncRequests.indexOf(action.seqId) === -1) {
return state;
}
return reducer(state, action);
});
为此向詹姆斯大声喊叫。非常好的解决方案,在他的博客 post.
中有很好的解释Thunk 将 dispatch
和 getState
作为参数。
如果您将当前路线保留在您所在州的某处,您可以在 API 回调中检查您是否仍在与 getState().routing.path
或类似的页面上,并且 return
如果自 API 调用开始后它发生了变化。
如果您不保持当前路线处于状态,您可以改为阅读this.context.router
in your component (don’t forget to define contextTypes
to get it!) and pass it to the action creator. The action creator can then use router.isActive()
来检查请求前后我们是否仍在同一路径上。
最后,您可以不使用相同的状态来编辑和添加项目。你的状态形状可以看起来像 { drafts: { newItem: ..., 1: ..., 2: ... } }
,你可以在 drafts.newItem
中保留“添加”表单,并通过相应实体的 ID 保留任何“编辑”表单。这样他们就永远不会互相覆盖,并且作为奖励,可以保留正在进行的编辑,例如如果您按“返回”然后再次转到表单(当然取决于您是否希望在您的用户体验中使用它)。