我什么时候必须在useReducer中使用排列运算符



我注意到,在许多useReducer示例中,排列运算符用于减缩器中,如下所示:

const reducer = (state, action) => {
switch (action.type) {
case 'increment1':
return { ...state, count1: state.count1 + 1 };
case 'decrement1':
return { ...state, count1: state.count1 - 1 };
case 'increment2':
return { ...state, count2: state.count2 + 1 };
case 'decrement2':
return { ...state, count2: state.count2 - 1 };
default:
throw new Error('Unexpected action');
}
};

然而,在我的许多实践中,我删除了...state,并且没有任何问题。我知道...state用于保留其余状态的状态,但减少器是否已经保留了这些状态,因此不需要...state

有人能给我举一些例子吗?...state是必须的,当用useReducer钩子移除时会导致问题?提前感谢!

否,单独的reducer函数将不会保留现有状态,您应该始终处于习惯性的浅层复制现有状态。它将帮助您避免一类状态更新错误。

我能想到的一个例子是,当扩展现有状态时,可能不是是必要的,那就是它不是对象的情况。

例如:a";计数";状态

const reducer = (state = 0, action) => {
// logic to increment/decrement/reset state
};

例如:单个";"状态";状态

const reducer = (state = "LOADING", action) => {
// logic to update status state
};

对于具有多个属性的任何状态对象,扩展现有状态都是必须,因为每次都会返回状态对象,以保留所有未更新的现有状态属性。

编辑1

你能举一个例子吗?当没有浅层复制导致状态更新错误时?

const initialState = {
data: [],
loading: false,
};
const reducer = (state, action) => {
switch(action.type) {
case LOAD_DATA:
return {
...state,
loading: true,
};

case LOAD_DATA_SUCCESS:
return {
...state,
data: action.data,
loading: false
};
case LOAD_DATA_FAILURE:
return {
loading: false,
error: action.error,
};
default:
return state;
}
};

如本例所示,在数据加载失败时,reducer忽略了将现有状态复制到新状态对象中。

const [state, dispatch] = useReducer(reducer, initialState);
...
useEffect(() => {
dispatch({ type: LOAD_DATA });
// logic to fetch and have loading failure
}, []);
return (
<>
...
{state.data.map(...) // <-- throws error state.data undefined after failure
...
</>
);

任何假定state.data始终存在或始终是数组的选择器或UI逻辑都将失败并出现错误。初始渲染将起作用,因为state.data是一个空数组,可以映射,但在加载错误时,state.data将从状态中删除。

最新更新