Réagir + useState () + previousState
Je suis assez nouveau pour réagir et j'ai des problèmes pour comprendre le hook useState - ou plus précisément l'aspect du previousState .
Un hook useState normal, et probablement l'exemple le plus courant, ressemble à ceci:
import React, { useState} from 'react';
export default function CounterHooks({ initialCount }){
const [count, setCount] = useState(initialCount);
return (
<div>
<button onClick={() => setCount(count -1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
)
}
Ce que je comprends jusqu'à présent, c'est ce qui suit:
- J'appelle la fonction useState () / Hook? et passez l'argument de l'état initial (initialCount)
- Je récupère un tableau que je détruis immédiatement dans les variables count et setCount (qui est la fonction)
- Avec setCount () je peux mettre à jour l'état et donc la variable count
Jusqu'ici tout va bien, je pense ...;)
Parfois, je vois le même exemple de compteur avec prevState (prevCount) que je ne comprends pas:
<button onClick={() => setCount(prevCount => prevCount -1)}>-</button>
Que se passe t-il ici? Cette partie, je ne comprends pas. Mes pensées jusqu'à présent:
- Dans ce cas, j'accède en quelque sorte à la valeur de comptage précédente.
- setCount attend maintenant une fonction
- setCount est maintenant exécuté de manière asynchrone
- D'où vient cette fonction?
- D'où vient prevCount?
- Quand j'exécute ceci, qu'est-ce qui est mis dans prevCount?
Comprenez-vous ma confusion? Je ne sais pas comment je devrais encadrer cela différemment ...
Merci beaucoup pour votre aide.
Réponses
Tout d'abord, vous pouvez voir l'explication officielle ici .
Dans ce cas, j'accède en quelque sorte à la valeur de comptage précédente.
Vous n'accédez pas d'une manière ou d'une autre à la valeur de comptage précédente. Si vous utilisez une mise à jour fonctionnelle et donnez une fonction de rappel au setter, elle vous renvoie l'état précédent et vous utilisez cette valeur dans votre fonction de rappel.
setCount attend maintenant une fonction
Puisque vous fournissez une fonction, il peut l'utiliser.
setCount est maintenant exécuté de manière asynchrone
En fait non. Ce n'est pas une fonction asynchrone. Il fournit simplement l'état précédent et vous l'utilisez. Les setters d'état ne sont pas asynchrones, la mise à jour d'état l'est.
D'où vient cette fonction?
D'où vient prevCount?
Déjà répondu.
Quand j'exécute ceci, qu'est-ce qui est mis dans prevCount?
Vous indiquez ce que vous souhaitez définir dans le nouvel état. Dans votre exemple, vous voulez incrémenter countde 1, donc vous fournissez+ 1
Voici une explication naïve de cette logique. Juste un naïf. J'ajoute ceci pour illustrer la logique de rappel, ce n'est pas lié à ReactsetState.
let state = 5;
function setState(val) {
if (typeof val === "function") {
return val(state);
}
return val;
}
const stateWithFunctionalUpdate = setState(prev => prev + 1);
const stateWithNormalUpdate = setState(9);
console.log(stateWithFunctionalUpdate);
console.log(stateWithNormalUpdate);
Peut - être que cet exemple conviendrait pour imiter la logique de réglage d'état de React. Encore une fois, juste une approche naïve.
let state = 5;
function setState(val) {
if (typeof val === "function") {
state = val(state);
} else {
state = val;
}
}
setState(9);
setState(prev => prev + 1);
console.log("state", state);
Regardons l' implémentation réelle de useState(sans typages):
export function useState(initialState) {
return useReducer(
basicStateReducer,
// useReducer has a special case to support lazy useState initializers
initialState
);
}
Eh bien, il utilise juste useReducerderrière les rideaux. Il définit l'état initial et utilise basicStateReducer qui est:
function basicStateReducer(state, action) {
return typeof action === "function" ? action(state) : action;
}
Comme notre approche naïve, il cherche le type de actionet se comporte en fonction de cela. Enfin, voici ce qui useReducer revient :
return [workInProgressHook.memoizedState, dispatch];
Donc, à la fin de la journée, si nous fournissons une fonction à useState, il la prend, puis l'exécute sur notre état et renvoie la valeur.
Voici mon avis comment je comprends:
Dans ce cas, j'accède en quelque sorte à la valeur de comptage précédente. -> setCount vérifiera param, si le param est un callback, il appellera ce call back et passera l'état précédent pour param. Le résultat du rappel sera l'état suivant.
setCount attend maintenant une fonction -> oui, la fonction gère la logique et renvoie l'état suivant.
setCount est maintenant exécuté de manière asynchrone -> cette fonction est synchronisée mais après elle renvoie le résultat. Le hook pour setCount enverra un événement pour mettre à jour l'état suivant
D'où vient cette fonction? -> vous pouvez faire n'importe quoi en fonction tant que param sera l'état actuel et retournera un état suivant.
D'où vient prevCount? -> sera passé lors de l'appel setCount (il est obtenu à partir de l'état actuel).
Quand j'exécute ceci, qu'est-ce qui est mis dans prevCount? -> état actuel de setCount.
=> Exemple pour passer une valeur ou un rappel à setCount ici: hook useState, fonction setState. Accéder à la valeur d'état précédente