【问题标题】:Can we cancel out api response when the react router is changed?更改反应路由器时,我们可以取消 api 响应吗?
【发布时间】:2016-04-15 01:05:56
【问题描述】:

我在 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 延迟发送。当我打开表单以添加项目时,此表单将填充来自响应的数据。

【问题讨论】:

    标签: javascript reactjs react-router redux


    【解决方案1】:

    Thunk 将dispatchgetState 作为参数。

    如果您将当前路由保留在您的状态中的某个位置,您可以在 API 回调中检查您是否仍与 getState().routing.path 或类似的东西在同一页面上,以及 return 如果自 API 以来它已更改通话开始。

    如果你不保持当前路由状态,你可以改为在你的组件中读取this.context.router(不要忘记定义contextTypes来获取它!)并将其传递给动作创建者。然后,动作创建者可以使用router.isActive() 来检查我们在请求之前和之后是否仍在同一路径上。

    最后,您可以使用相同的状态来编辑和添加项目。您的状态形状可能看起来像{ drafts: { newItem: ..., 1: ..., 2: ... } },您可以将“添加”表单保留在drafts.newItem,并通过相应实体的 ID 保留任何“编辑”表单。这样他们就永远不会互相覆盖,并且作为奖励,可以保留正在进行的编辑,例如如果您按“返回”然后再次转到表单(当然取决于您是否希望在您的用户体验中使用它)。

    【讨论】:

    • 我不认为检查我们在哪条路线上是一个好主意。一种情况,如果我们单击一个项目的编辑,那么我们快速返回并单击第二个项目的编辑项目。如果第一个请求的响应晚于第二个请求,那么即使我们在同一条路线上,表单也会填充虚假数据。
    • 不知道为什么会这样。我认为不同的项目有不同的编辑路线,不是吗?
    • 我遵循了您的第一种方法并将路由存储到存储中,我使用了 react-router-redux。感谢您的回复..
    【解决方案2】:

    前几天我看到了这个blog post,我认为第二部分描述了你在寻找什么。您不一定要取消请求,但忽略响应。

    基本上,您想创建一个外部 reducer,它会跟踪您对具有唯一 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;
    }
    

    然后限制子reducer:

    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);
    });
    

    为此向詹姆斯大声疾呼。非常好的解决方案,并且在他的博客文章中得到了很好的解释。

    【讨论】:

    • 我知道了基本概念,但我不明白商店部分。
    猜你喜欢
    • 2017-07-22
    • 2017-09-03
    • 1970-01-01
    • 2017-08-25
    • 2018-01-05
    • 2019-03-01
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多