我搜索了类似的问题,但找不到合适的帖子(...尽管我怀疑以前曾问过这个问题),所以我事先表示歉意。
我现在已经将Redux与React一起用于几个项目,并且刚刚开始在一个学习项目中包含immutable.js和Reselect。我的测试/学习项目只是将一个大型JSON对象加载到状态中,然后使用Reselect抓取它的一部分,然后传递到我的组件中。这是我正在加载的对象的示例:
export const formState = {
progress: {
groupId: 3,
questionId: 5,
},
content: [
{
group: { id: 1, name: 'Company', description: 'Data regarding your company.', questions: 2 },
questions: [
{
id: 1,
type: 'textField',
label: 'Required *',
inputLabelProps: { shrink: true },
text: 'group 1 question 1',
answer: '',
},
...
...
...
]
}
此对象通过在componentWillMount()中触发的动作加载到状态,然后该动作流经化简器,最终触发组件内的mapStateToProps,如下所示:
const mapStateToProps = (state) => {
console.log(state);
return {
progress: getProgressData(state),
content: getContentData(state),
};
};
这按预期工作。该组件有两个按钮,使您可以遍历上述“总体状态”的内容对象中的问题数组。
此外,当您按下前进或后退按钮遍历上述问题数组时,进度对象将通过操作进行更新,然后在化简器中通过以下操作进行更新:
switch (action.type) {
case UPDATE_PROGRESS:
formState = state.get('formState');
formState.progress = action.payload;
console.log(formState);
return state
.set('formState', formState);
所以这很奇怪。第一次单击前进或后退时,它起作用,并且看到对象得到更新,并且下一个问题显示在组件中。如预期的那样。
如果我单击后退或再次单击下一步,则看到动作被触发,我看到在化简器中反映了适当的状态,但是不再在mapStateToProps的console.log中看到状态。它永远不会达到那个程度。关于我做错了什么的任何想法?
注意:我似乎不只是通过以下方式更新reducer中的状态,这似乎很奇怪: 返回状态 .setIn(['formState','progress'],formState)
我最初尝试这样做,但是得到了无效的密钥路径。考虑到我正在通过fromJS()将初始状态转换为immutable.js映射,这对我来说很奇怪,因此我认为其中包含的任何内容都是映射或列表或任何适当的内容,因此可以通过这种方式寻址...无论如何,我认为一旦解决了上述问题,便会解决该问题。也就是说,除非它们相关。
一如既往,如果这是一个重复的问题,我们将不胜感激,诚挚的歉意。
谢谢!
答案 0 :(得分:2)
Immutable.js函数Collection.get返回给定键后面的值,在这种情况下,键是指向对象的指针。当前,您更改该对象,然后使用Collection.set将其重新设置。对象已更改,但指向该对象的指针(即您状态中存储的值)没有更改。因此,您的状态在技术上不会发生变化,并且组件也不会更新。
发生此问题的原因是您在Immutable.js集合中存储了一个普通对象。您应该只使用简单的对象,或者仅使用Immutable.js集合安全使用它。不要混在一起。
也使state.formState成为Immutable.js集合。然后通过Immutable.js方法对其进行更改。
switch (action.type) {
case UPDATE_PROGRESS: {
const formState = { ...state.formState };
formState.progress = action.payload
console.log(formState);
return { ...state, formState };
}
如果您决定使用Immutable.js,则应确保不要留在任何普通的javascript对象中,因为它们可以绕开Immutable.js提供的保护。
设置一个普通的javascript对象。
const stateCopy = { ...state };
如果您决定不使用Immutable.js,则必须注意不要意外更改状态。最简单的方法是使用传播语法复制状态:browser
答案 1 :(得分:1)
您不应该在reducer中更新状态。几乎总是会导致堰式行为immutable-update-patterns。您是否尝试过返回新对象?即
switch (action.type) {
case UPDATE_PROGRESS:
return {
...state,
formState: {
...state.formState,
progress: action.payload
}
};