代码之家  ›  专栏  ›  技术社区  ›  alt-rock

反应还原剂突变

  •  0
  • alt-rock  · 技术社区  · 7 年前

    template connect() 不要重新渲染。如何以正确的方式编写这个减速机以避免状态突变?

    减速器:

    case UPDATE_STYLE:
      // Update the style value of the template
      let newState = {
        ...state
      }
      newState
          .templates[action.payload.selectedTemplateType]
          .content[action.payload.selectedTemplate]
          .template
          .styles[action.payload.styleKey][action.payload.fieldKey]
          .value = action.payload.value;
    
      // mutated state - not firing rerenders
      return newState;
    

    启动调度呼叫(工作):

    onStyleChange(styleKey, fieldKey, value){
        this.props.dispatch(
          updateStyle(selectedTemplateType, selectedTemplate, styleKey, fieldKey, value)
        );
      }
    

    子组件的连接方式(不渲染):

    const mapStateToProps = (state) => ({
      templates: state.templates.templates,
      selectedTemplateType: state.templateTypeSelection.selectedTemplateType,
      selectedTemplate: state.templateSelection.selectedTemplate
    })
    
    export default connect(mapStateToProps)(Index)
    
    2 回复  |  直到 7 年前
        1
  •  0
  •   Sebastian Rothbucher    7 年前

    另一篇文章已经提到deepcopy是一个快速的解决方案(尽管您可能会失去性能)。然而,尽管这有点棘手,但是扩展语法( ...

    let newState = { ...state, templates: {
      { ...state.templates, [action.payload.selectedTemplateType]: {
        { ...state.templates[action.payload.selectedTemplateType], content: {
          { ...state.templates[action.payload.selectedTemplateType].content, [ // and so on
    

    至少,您只需要为实际更改的内容创建新对象。

    注意:您可能想看看immutableJS,它提供了很多帮助,而且不太容易出错。例如,有 mergeDeep

    当你不想做如此深刻的转变时,npm上也有deepmerge模块(只是google的“mergedeepnpm”);我只是没试过这些。。。

        2
  •  0
  •   Benjamin Hao    7 年前

    state.templateTypeSelection.selectedTemplateType 是同一个对象,即使对象内部的某些属性发生了更改。其他道具也有同样的问题。因此,对于组件来说,这些道具是相同的道具,因此组件不会重新提交。

    有一些解决办法。1使你的状态变平(似乎不适用于你)2深入复制减速机状态。3在执行`mapstatetops操作时,请尝试映射最内部的属性,而不是顶级属性。

    对于解决方案2,您可以为reducer状态的顶级属性创建类。例如,可以创建一个名为 TemplateTypeSelection state.templateTyepeSelection . 在reducer中处理操作时,对于新状态,使用 new TemplateTypeSelection(prevState.templateTypeSelection) 为state.templateTypeSelection创建新对象(您可能希望使用构造函数来执行 state.templateTypeSelection ). 因为state.templateTypeSelection现在是一个新对象,所以您的组件现在应该能够重新提交。这个方法的问题是,因为每次处理一个动作时,都会创建一个新对象,所以可能会有一些不必要的重述(这只是一个如何做到这一点的例子。Prob不是一个好例子,因为在你的组件中,你正在连接 state.templateTypeSelection.selectedTemplateType ,不是 state.templateTypeSelection模板 . 希望你能理解。)

    根据我的经验,方法2和方法3的结合效果最好。此外,您可能需要考虑将减速器拆分为多个减速器。