Est-il nécessaire d'utiliser l'opérateur de propagation dans useReducer?
EDIT: après avoir vérifié la réponse de Brian, j'ai découvert que même dans le 2ème exemple, la suppression ...state
provoquerait le même comportement que le 1er exemple, donc cette question était mal posée. Je ne suis pas sûr de ce qui a fait voir le mauvais comportement et je m'excuse pour tout inconvénient causé. La réponse de Brian est une bonne explication de l'utilisation.
Comparez les 2 extraits de code suivants, ils font la même chose en mettant à jour 2 états à la fois avec un initialState
, sauf que l'un utilise useState
et l'autre utilise 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>
En cas de suppression ...state
dans le premier exemple, il définit l'état sur une seule paire clé / valeur et ne fonctionne donc plus. Je m'attendais à ce que la même chose se produise dans le deuxième exemple, mais ce n'est pas le cas. le deuxième exemple fonctionne bien avec l'opérateur d'épandage supprimé.
J'ai 3 questions pour le 2ème exemple:
- à quoi sert l'opérateur de diffusion?
- pourquoi ça marche encore après avoir supprimé les opérateurs de propagation?
- Si cela fonctionne bien sans l'opérateur d'épandage, cela signifie-t-il que l'opérateur d'épandage n'est pas nécessaire dans le 2ème exemple?
Réponses
Je comprends que c'est une question très similaire à celle-ci , mais je donne quand même une réponse pour empêcher les futurs lecteurs d'obtenir des informations incorrectes.
Ni useState
ni useReducer
aucune fusion des valeurs précédentes. Toute conservation des valeurs d'état précédentes est de votre responsabilité lors de la mise à jour de l'état (soit dans l' setState
appel, soit dans la définition de la fonction de réduction).
Vous pouvez le voir clairement dans le code modifié ci-dessous. Tout ce que j'ai changé, c'est de retirer le ...state
de chaque boîtier de commutateur.
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>
La raison pour laquelle l'opérateur de diffusion est utilisé si fréquemment à cette fin est que c'est la méthode la moins fastidieuse pour mettre toutes les valeurs inchangées dans le nouvel objet.