web-dev-qa-db-fra.com

React Hooks - useEffect se déclenche même si l'état n'a pas changé

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.

7
Enrique Moreno Tent

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]);

référence de l'API du crochet useEffect

0
Pavel Ye

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.

0
Baroudi Safwen

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]);
0
Dan Hunex