简体   繁体   中英

Is it necessary to use the spread operator in useReducer?

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 :

  1. 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>

  1. 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:

  1. what is the use of the spread operator?
  2. why does it still work after removing the spread operators?
  3. If it works well without the spread operator, does that mean the spread operator is not needed in 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM