是否可以在 useReducer 中不分派地更改状态?
Is it possible to change state without dispatch in useReducer?
我发现 state.elements 在控制台中已更改,即使我还没有发送。
这是什么原因?
const initialState = { elements: [['apple','banana'],['rabbit','cat']] };
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = React.useReducer(reducer, initialState);
const changeList=()=>{
const elementsArray = Array.from(state.elements);
elementsArray[0][0]='Tiger'
}
return (
<>
Count: {state.elements}
<button onClick={changeList}>Change List without dispatch</button>
</>
);
}
是的,在 useReducer 中可以在不分派的情况下更改状态。
就像 React 中的任何状态一样,它是可以改变的。 useReducer
州也不例外。
const changeList=()=>{
const elementsArray = Array.from(state.elements);
elementsArray[0][0] = 'Tiger'; // <-- state mutation
}
数组通过引用复制,所以即使 elementsArray
是state.elements
数组的副本,数组元素仍然是对原始元素的引用仍在 state.elements
。将 elementsArray[0][0]
设置为值 "Tiger"
与将 state.elements[0][0]
设置为 "Tiger"
具有相同的效果。
React 中的突变是一个巨大的禁忌,一种反模式。你尤其不要改变状态或道具。状态和道具将被视为不可变对象。这就是为什么状态更新总是需要创建 新对象引用。
不可变更新示例:
在这里你浅拷贝了正在更新的每个级别的状态深度。浅层复制对象属性的 Spread 语法,以及 Array.prototype.map
将数组元素浅层复制到新数组中。
function reducer(state, action) {
switch (action.type) {
case "update_animal":
const { index1, index2, value } = action.payload;
return {
...state,
elements: state.elements.map((outerEl, indexOuter) =>
indexOuter === index1
? outerEl.map((innerEl, indexInner) =>
indexInner === index2 ? value : innerEl
)
: outerEl
)
};
... other cases ...
default:
return state;
}
}
...
dispatch({
type: "update_animal",
payload: {
index1: 0,
index2: 0,
value: "Tiger",
}
});
我发现 state.elements 在控制台中已更改,即使我还没有发送。 这是什么原因?
const initialState = { elements: [['apple','banana'],['rabbit','cat']] };
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = React.useReducer(reducer, initialState);
const changeList=()=>{
const elementsArray = Array.from(state.elements);
elementsArray[0][0]='Tiger'
}
return (
<>
Count: {state.elements}
<button onClick={changeList}>Change List without dispatch</button>
</>
);
}
是的,在 useReducer 中可以在不分派的情况下更改状态。
就像 React 中的任何状态一样,它是可以改变的。 useReducer
州也不例外。
const changeList=()=>{
const elementsArray = Array.from(state.elements);
elementsArray[0][0] = 'Tiger'; // <-- state mutation
}
数组通过引用复制,所以即使 elementsArray
是state.elements
数组的副本,数组元素仍然是对原始元素的引用仍在 state.elements
。将 elementsArray[0][0]
设置为值 "Tiger"
与将 state.elements[0][0]
设置为 "Tiger"
具有相同的效果。
React 中的突变是一个巨大的禁忌,一种反模式。你尤其不要改变状态或道具。状态和道具将被视为不可变对象。这就是为什么状态更新总是需要创建 新对象引用。
不可变更新示例:
在这里你浅拷贝了正在更新的每个级别的状态深度。浅层复制对象属性的 Spread 语法,以及 Array.prototype.map
将数组元素浅层复制到新数组中。
function reducer(state, action) {
switch (action.type) {
case "update_animal":
const { index1, index2, value } = action.payload;
return {
...state,
elements: state.elements.map((outerEl, indexOuter) =>
indexOuter === index1
? outerEl.map((innerEl, indexInner) =>
indexInner === index2 ? value : innerEl
)
: outerEl
)
};
... other cases ...
default:
return state;
}
}
...
dispatch({
type: "update_animal",
payload: {
index1: 0,
index2: 0,
value: "Tiger",
}
});