javascript - 在什么情况下忽略 useReducer 中的扩展运算符会导致错误?
问题描述
在我看到的大多数useReducer
示例中,扩展运算符已被用于保存状态。但是,在我所有的实践中,忽略它从未造成任何问题。似乎reducer 能够在没有扩展运算符的情况下保留状态本身。检查以下示例:
const initialState = {
color: 'black',
bgColor: 'white'
}
const reducer = (state, action) => {
switch (action.type) {
case 'dawn':
return {
...state,
color: 'white',
bgColor: 'purple'
}
case 'reset':
return initialState
default:
return {
state
}
}
}
const UseReducerColorSetter = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const { color, bgColor } = state;
return (
<>
<div style={{ color: `${color}`, backgroundColor: `${bgColor}` }} className='card'>
Hello
</div>
<button onClick={() => dispatch({ type: 'dawn' })}>Dawn mode</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</>
)
}
在这个例子中,移除...state
不会导致任何问题,没有状态改变,没有控制台错误等。
在这个问题中,我问:是否有必要在 useReducer 中使用扩展运算符,忽略扩展运算符会导致问题useState
,但仍然没有问题useReducer
。
有人可以为我提供一些忽略传播运算符导致问题的例子useReducer
吗?减速器可以保持状态吗?
解决方案
这是一个运行示例,显示如果您不替换减速器中的所有对象属性,它们将丢失。将控制台记录的初始值与打印的结果进行比较。
const initialState = {
color: "black",
bgColor: "white"
};
const reducer = (state, action) => {
switch (action.type) {
case "dawn":
return {
bgColor: "purple" // Updated to only return one property to illustrate the problem
};
case "reset":
return initialState;
default:
return {
state
};
}
};
function App() {
const [state, dispatch] = React.useReducer(reducer, initialState);
React.useEffect(() => {
console.log("Initial: ", state)
dispatch({ type: "dawn" });
}, []);
return <div>{JSON.stringify(state)}</div>;
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
注意reducer 函数的签名 (state, action) => newState
。此函数返回新状态。所以无论你return
从减速器中得到什么,它都是新的状态值。这意味着在不传播根状态对象的情况下,您将丢失任何未在新对象中明确设置的值。
要直接回答您的问题,当您的状态是数组或对象时,不将先前的状态传播到 reducer 更新会导致错误,并且您不会手动替换该结构中的每个值。
如果您总是设置每个对象属性或返回之前的状态,您将永远不会遇到错误。这是您在问题中给出的场景,这就是为什么它似乎没有必要。
推荐阅读
- sql - SQL sum 和上一行
- c# - SignalR 集线器客户端无法在 SignalR 管道外部正确解析
- cups - 无法使用 cups4j 从杯子 2.0.1 中获取纸张颜色
- selenium - 如何在 Jenkins 上运行 CI selenium side runner 测试
- javascript - 合并 2 个数组,更新值
- .net-core - 无法使用 FormattableString
- c++ - 为什么我得到
() 函数不能接收元组的子类? - python - Airflow:原生运营商与容器
- perl - 如何使用 Mojo::Useragent 放置文件?
- sql - 使用 Laravel 和 SQL Server 在事务中插入具有不同数据类型的语句失败