【问题标题】:Removing item from redux-stored list and redirect back to list - delay props evaluating?从 redux 存储的列表中删除项目并重定向回列表 - 延迟道具评估?
【发布时间】:2016-08-29 19:01:28
【问题描述】:

我正在查看步骤列表。每个步骤都可以从“查看”屏幕中“查看”和“删除”。 我的StepDetails 组件通过使用简单的steps.find(...) 从存储的steps 部分获取相应的步骤来绑定到redux 存储:

const mapStateToProps = (state, ownProps) => {
  let stepId = ownProps.params.stepId;
  let step = state.steps.find(s => s.id === stepId);
  return {step};
};

现在,当我(从“详细信息”中)点击“删除步骤”时,我希望将此步骤从商店中删除,并且我想导航到列表视图。

在删除时调用了 redux 操作,它返回新的步骤列表而没有删除这个,然后调用重定向:

const deleteStep = (stepId) => {
  return dispatch => {
    return stepsApi.deleteStep(stepId).then(steps => {
      dispatch(action(STEPS_LIST_CHANGED, {steps}));
      // react-router-redux action to redirect
      dispatch(redirectToList());
    })
  }
};

这很好,可以满足我的要求,但有一个缺点:当调用 STEPS_LIST_CHANGED 操作并从列表中删除 step 时,我的组件的 mapStateToProps 在此重定向之前被调用。结果是mapStateToProps 显然无法再找到此步骤,并且我的组件给我错误提示步骤未定义等。

我可以做的是检查是否定义了提供给组件的步骤,如果不渲染任何内容等。但这是一种我不太喜欢的防御性编程风格,因为我不希望我的组件知道什么如果它得到错误的数据怎么办。

我也可以交换动作调度顺序:先重定向然后改变状态,但是感觉也不对(逻辑上你想先删除然后重定向)。

你如何处理这种情况?

编辑: 我最终的结果是将这个 null/undefined-check 放入容器组件(一个执行 redux 接线的组件)。使用这种方法,我不会用不必要的逻辑来混淆我的演示组件。它也可以被抽象为更高阶的组件(或可能是 ES7 装饰器)以在某些必需的道具不存在时呈现 null<div></div>

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    我可以想到两种方法:

    • 委派列表更改为重定向?例如:

      dispatch(redirectToList(action(STEPS_LIST_CHANGED, {steps})));
      
    • 处理空步组件忽略渲染:

      shouldComponentUpdate: function() {
          return this.state.steps != null;
      }
      

    【讨论】:

      【解决方案2】:

      你可以把你的return语句改成一个数组

      const mapStateToProps = (state, ownProps) => {
        let stepId = ownProps.params.stepId;
        let step = state.steps.find(s => s.id === stepId);
        return step ? [{step}] : []
      };
      

      这样你就可以在你的组件上做一个step.map() 并渲染它。

      【讨论】:

      • 对我来说感觉太hacky了,这个单元素数组在那里完全是人造的,没有提供太多价值但会给意图可读性带来噪音
      • @MichalOstruszka 实际上,您可能会在许多 API 上发现这一点,并且在您的函数保持纯净的同时,它的方法仍然有效。
      【解决方案3】:

      您面临的问题是您需要一个原子操作来执行删除和重定向。这是不可能的,因为 Redux 存储和 URL 是 two separate states,无法一次更新。

      因此,用户可以在短时间内看到:

      • 重定向前的空实体详细信息页面或
      • 重定向后列表中删除的实体。

      解决这个问题的一种方法是使用React.memo(或shouldComponentUpdate)并防止在实体消失后组件重新渲染:

      const entityWasDeleted = (prevProps, nextProps) => 
        prevProps.entity !== undefined && nextProps.entity === undefined
      
      export default React.memo(EntityDetailComponent, entityWasDeleted)
      

      这有点 hacky,因为 React.memo 不应该像这样使用,但是组件会在下一步中卸载,所以谁在乎呢。

      【讨论】:

        猜你喜欢
        • 2016-09-12
        • 1970-01-01
        • 2016-08-14
        • 2021-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-13
        • 1970-01-01
        相关资源
        最近更新 更多