从 redux 存储的列表中删除项目并重定向回列表 - 延迟道具评估?

Posted

技术标签:

【中文标题】从 redux 存储的列表中删除项目并重定向回列表 - 延迟道具评估?【英文标题】:Removing item from redux-stored list and redirect back to list - delay props evaluating? 【发布时间】: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>

【问题讨论】:

【参考方案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 不应该像这样使用,但是组件会在下一步中卸载,所以谁在乎呢。

【讨论】:

以上是关于从 redux 存储的列表中删除项目并重定向回列表 - 延迟道具评估?的主要内容,如果未能解决你的问题,请参考以下文章

通过重定向到贝宝并重定向回应用程序来创建商家帐户的贝宝集成

具有关系数据存储的列表和项目之间的关系(使用 react-redux)

如何在 Redux 中处理列表项

如何检测回访者并重定向到特定 URL? [关闭]

从规范化的 redux 存储中删除项目

Laravel 存储 GET 参数以重定向回