【问题标题】:Redux Reducer: key injection into stateRedux Reducer:将密钥注入状态
【发布时间】:2016-10-23 06:14:33
【问题描述】:

首先,我明白这是一种变异的状态变化;我知道我很丢脸。有时正确的方法似乎不是最聪明的,或者我至少不知道更好。

让我解释一下,我不想在不为预定义项目创建和交换旧状态和新状态的情况下将密钥注入我的状态。我只是想注入密钥一段时间,如果我不这样做,那么无论如何它们都会被清除。我的初始状态看起来像

{graphSite: {site: "default", graphBrowser: { graphID: '', graphKey:'' }, browsable:[] }};

我的 reducer 看起来像这样 **使用 babel es7 对象扩展运算符

case BROWSER: { state.graphSite.browsable[action.id] = action.payload
                return {...state}
               }

所以这会起作用,但是 redux 开发工具没有显示状态变化,尽管可浏览的数组是可访问的,这可能是因为我违背了规律,但如果我将更改扩展到:

case BROWSER:  { state.graphSite.browsable[action.id] = action.payload
                        return {...state, 
                                graphSite: {...state.graphSite, 
                                    graphBrowser: {...state.graphSite.graphBrowser},
                                    browsable: {...state.graphSite.browsable}   }
                                }
                            }

现在可在工具中正确显示可浏览,但理想情况下,这些是相同的。

所以问题是,对于不处于初始存储状态的动态键,操作状态的最佳方法是什么。这行得通,感觉就像我做错了什么,因为我操纵了原始状态。

【问题讨论】:

  • 你正在改变状态本身。 state.graphSite.browsable[action.id] = action.payload。您需要对状态进行深层复制,并按照您的方式改变副本,然后返回副本
  • 我希望动作 ID 足够动态,我不必跟踪可能的初始状态来更改。问题是没有什么可复制的,除非你改变原件并将其作为新的返回。否则 id 做正常的对象传播和我想要改变的部分。这主要是为了关键,因为如果这是一个数组,我不能保证异步调用的顺序

标签: dynamic key redux


【解决方案1】:

首先这个标题让我很困惑。 dynamic key injection 对我来说听起来太花哨了:P。

无论如何,您实际上想向您的browserble 添加一对新的。 你有:

case BROWSER: { state.graphSite.browsable[action.id] = action.payload
            return {...state}
           }

这是错误的(假设state 来自reducer 参数),因为您正在直接修改state 对象。

redux 的一个原理就是Changes are made with pure functions。 (redux 文档)。

FTFY:

case BROWSER: { 
  const nextState = JSON.parse(JSON.stringify(state)); // deep copy your state
  nextState.graphSite.browsable[action.id] = action.payload
  return nextState
}

这不是最有效的代码,JSON操作很昂贵。只是为了演示不直接改变状态对象的原理。

【讨论】:

    【解决方案2】:

    好的,我无法在对象传播的上下文中看到如何附加变量键并且没有创建初始存储状态。在复制状态然后返回附加的状态之后,这非常简单;两者都有效,这个只是现在没有修改原始状态。

    case BROWSER:  { let browser = {...state} 
                             browser.graphSite.browsable[action.id] = action.payload
                            return {...state, 
                                    graphSite: {...state.graphSite, 
                                        graphBrowser: {...state.graphSite.graphBrowser},
                                        browsable: {...browser.graphSite.browsable}
                                        }
                                    }
                                }
    

    不,谢谢你的反对票解构在这里很好用

    case BROWSER:  { let {graphSite: {browsable: browser}} = state
                             browser[action.id] = action.payload
    
                            return {...state, 
                                    graphSite: {...state.graphSite, 
                                        graphBrowser: {...state.graphSite.graphBrowser},
                                        browsable: {...browser}
                                        }
                                    }
                                }
    

    我也意识到我可以使用 deepFreeze 或 immutable 之类的东西来检查这些但要练习。

    【讨论】:

    • 注意:对象传播运算符浅拷贝你的状态。因此,您的代码仍在直接修改状态,这可能会导致意外错误。
    猜你喜欢
    • 2019-02-17
    • 2023-03-23
    • 2019-07-28
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 2020-06-19
    • 2021-01-08
    相关资源
    最近更新 更多