Redux reducer - 它会改变状态吗?

问题描述 投票:0回答:4

我遇到了以下redux减速机,虽然它工作正常,但我认为这是错误的:

export default (state = initState, action) => {
    switch (action.type) {
        case RESET_SCREEN:
            return Object.assign({}, state, initState);
        case MODIFY_ITEM:
            let itemId = state.item.id;
            state.items[itemId].item = action.item;
            return Object.assign({}, state, {items: state.items});
    }
}

RESET_SCREEN是否正确是正确的,因为它不会改变状态,但MODIFY_ITEM部分是坏的,因为它会发生变异?它会在哪些情况下受伤? (因为应用程序当前正在按预期运行)

MODIFY_ITEM的替代方案是什么?

reactjs redux react-redux
4个回答
1
投票

RESET_SCREEN是否正确是正确的,因为它不会改变状态

是的,这是对的。

但是MODIFY_ITEM部分很糟糕,因为它会发生变异

不,MODIFY_ITEM不改变状态:

这一行:state.items[itemId].item = action.item;变异对象(不是状态),但redux并不关心局部对象变异 - 它甚至都不知道。

只要您返回一个新引用 - 该对象的新副本,redux认为它是一个有效的新状态。

所以,按照redux, 这是状态突变:

case MODIFY_ITEM:
        let itemId = state.item.id;
        state.items[itemId].item = action.item;
        return state; // <-- because you are returning the same reference. BAD

这不是状态变异:

case MODIFY_ITEM:
    let itemId = state.item.id;
    state.items[itemId].item = action.item;
    return Object.assign({}, state, {items: state.items}); // <- A new Object. GOOD

您可能想要了解浅层检查和状态突变here


0
投票

您正在改变此行中的先前状态

state.items[itemId].item = action.item;

0
投票

你可以使用npm immer

它是一个小包,允许您以更方便的方式使用不可变状态。它基于copy-on-write mechanism


0
投票

为了保持状态的不变性,你可以像这样编写MODIFY_ITEM动作处理程序:

case MODIFY_ITEM:
    let itemId = state.item.id;
    return {...state, items: state.items.map((item, index) => {
        return index === itemId ? action.item : item
    })}
© www.soinside.com 2019 - 2024. All rights reserved.