J'ai mis en place un effet à l'intérieur de mon composant, qui change la vue si un autre attribut d'état change. Mais pour une raison quelconque, lorsque le composant monte, l'effet est exécuté, même si la valeur de detailIndex
n'a pas changé.
const EventsSearchList = () => {
const [view, setView] = useState('table');
const [detailIndex, setDetailIndex] = useState(null);
useEffect(() => {
console.log('onMount', detailIndex);
// On mount shows "null"
}, []);
useEffect(
a => {
console.log('Running effect', detailIndex);
// On mount shows "null"!! Should not have run...
setView('detail');
},
[detailIndex]
);
return <div>123</div>;
};
Pourquoi cela arrive-t-il?
UPDATE : Dans le cas où ce n'est pas clair, ce que j'essaie est d'exécuter l'effet lorsque le composant est mis à jour car detailIndex
change. PAS quand il monte.
useEffect
est toujours exécuté après le rendu initial.
De docs :
UseEffect fonctionne-t-il après chaque rendu? Oui! Par défaut, il s'exécute à la fois après le premier rendu et après chaque mise à jour. (Nous parlerons plus tard de la façon de personnaliser cela.) Au lieu de penser en termes de "montage" et de "mise à jour", vous pourriez trouver plus facile de penser que les effets se produisent "après le rendu". React garantit que le DOM a été mis à jour au moment où il exécute les effets.
En ce qui concerne votre code, ce qui suit ne s'exécutera qu'une fois car aucune dépendance n'est spécifiée (useEffect
prend un tableau facultatif de dépendances comme deuxième argument):
useEffect(() => {
console.log('onMount', detailIndex);
// On mount shows "null" -> since default value for detailIndex is null as seen above
// const [detailIndex, setDetailIndex] = useState(null);
}, []);
Et cela ne fonctionnera que lorsque detailIndex
changera (essayez d'appeler setDetailIndex
dans le précédent useEffect
):
useEffect(() =>
// ... effect code
}, [detailIndex]);
Dans mon cas, le composant a continué à se mettre à jour même si j'ai utilisé le deuxième argument dans useEffect () et que j'imprimais l'argument pour m'assurer qu'il ne changeait pas et qu'il ne changeait pas. Le problème était que je rendais le composant avec map () et qu'il y avait des cas où la clé a changé, et si la clé change, pour réagir c'est un objet complètement différent.
Vous pouvez ajouter un deuxième garde, vérifiez si detailIndex a changé par rapport à la valeur initiale dit -1
useEffect(
a => {
if(detailIndex != -1)
{ console.log('Running effect', detailIndex);
// On mount shows "null"!! Should not have run...
setView('detail');
}},
[detailIndex]);