EDIT: after checking Brian's answer, I found out that even in the 2nd example, removing ...state
would cause the same behaviour as the 1st example, so this question was wrong to ask. I'm not sure what made see the wrong behaviour and apologize for any inconvenience caused. Brian's answer is a good explanation of the use.
Compare the following 2 code snippets, they do the same thing by both updating 2 states at once with an initialState
, except one uses useState
and the other one uses useReducer
:
useState
const {useState} = React; const initialState = { name: 'John', age: 20 }; const Example = () => { const [state, setState] = useState(initialState); const handleName = () => { setState({...state, name: 'Tom'}); } const handleAge = () => { setState({...state, age: 30}); } return ( <div> <p>{state.name}</p> <p>{state.age}</p> <button onClick={handleName}> Click to change name </button> <button onClick={handleAge}> Click to change age </button> </div> ); }; ReactDOM.render( <Example />, document.getElementById("react") );
<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="react"></div>
useReducer
const {useReducer} = React; const initialState = { name: 'Tom', age: 30 } const reducer = (state, action) => { switch (action.type) { case 'name': return { ...state, name: 'John' } case 'age': return { ...state, age: 25 } default: return state } } const Example = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>Name: {state.name}</p> <p>Age: {state.age}</p> <button onClick={() => dispatch({ type: 'name' })}>Click to update name</button> <button onClick={() => dispatch({ type: 'age' })}>Click to update age</button> </div> ) }; ReactDOM.render( <Example />, document.getElementById("react") );
<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="react"></div>
If removing ...state
in the first example, it sets the state to a single key/value pair thus no longer works. I was expecting the same thing to happen in the second example, but it didn't. the second example works well with the spread operator removed.
I have 3 questions for the 2nd example:
I understand that this is a very similar question to this one , but I'm giving an answer anyway to hopefully prevent future readers from getting incorrect information.
Neither useState
nor useReducer
do any merge of previous values whatsoever. Any retention of previous state values is your responsibility during the state update (either in the setState
call, or in the reducer function definition).
You can see this plainly in the modified code below. All I have changed is removing the ...state
from each switch case.
const {useReducer} = React; const initialState = { name: 'Tom', age: 30 } const reducer = (state, action) => { switch (action.type) { case 'name': return { name: 'John' } case 'age': return { age: 25 } default: return state } } const Example = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>Name: {state.name}</p> <p>Age: {state.age}</p> <button onClick={() => dispatch({ type: 'name' })}>Click to update name</button> <button onClick={() => dispatch({ type: 'age' })}>Click to update age</button> </div> ) }; ReactDOM.render( <Example />, document.getElementById("react") );
<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="react"></div>
The reason the spread operator is used so frequently for this purpose is it's the least tedious method for putting all unchanged values into the new object.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.