3 votes

Comment fonctionne le crochet React useState et useCallback lorsque useCallback n'a pas de dépendances ?

Je suis en train d'étudier react-hook récemment. J'ai rencontré un problème qui me rend incapable de comprendre dans le processus de la pratique.

import React, { useState, useCallback } from 'react';
const set = new Set();

function Demo() {
  const [count, setCount] = useState(0);

  const changeValue = useCallback(() => {
    setCount(count + 1);
  }, []); 

  set.add(count);
  console.log('size: ', set.size);

  return(
    <div>
      <p>Hello React Hook</p>
      <p>{count}</p>
      <button onClick={changeValue}>count++</button>
    </div>
  )
}

export default Demo;

// If you click the button multiple times, the output is:
// size: 1
// size: 2
// size: 2

J'ai écrit un timer en utilisant react-hook. Comme je m'y attendais, la valeur de comptage affichée est toujours 1, car je n'ai pas utilisé count comme dépendance de useCallback.

Mais ce que je n'arrive pas à comprendre c'est console.log('size: ', set.size) seulement imprimé trois fois, pourquoi ? Chaque fois que je clique sur le bouton count++ pour que la fonction Démonstration soit réexécutée. Donc, à chaque fois que je clique sur le bouton, ne devrait-on pas console.log('size: ', set.size) sera exécuté ? Mais en fait, il n'a été exécuté que trois fois.

Et pourquoi size garder 2 inchangé ? Je comprends que setCount remplacera un nouveau count à chaque fois, donc size ne devrait pas augmenter ?

Veuillez m'aider à répondre à mes doutes, merci beaucoup.

Vous pouvez tester mon code aquí .

4voto

C-link Nepal Points 10815

El Demo sera rendu à nouveau chaque fois que son état sera modifié. Ainsi, il aura la taille 1 puisque vous avez ajouté l'état count à l'ensemble :

set.add(count); // 0 in initial render, size is 1

Maintenant, quand vous cliquez sur le bouton, il utilisera le callback useCallback qui est mémorisé par react. Cela signifie qu'il va d'abord vérifier s'il a une valeur en cache ou non. Donc, au premier clic, il n'a pas de valeur en cache. Et donc il appelle son callback pour définir (mettre à jour) l'état du compte. Maintenant, le compte est 1 et vous avez également ajouté le compte dans l'ensemble.

set.add(count); // 1 in first click, size is 2

Lors des clics suivants, useCallaback a mis en cache la valeur du compte mais vous n'avez pas défini le compte dans le second paramètre du hook useCallback et donc il retournera juste la valeur mise en cache qui est 1 - l'état du compte. Et il retournera toujours cette valeur. Encore une fois, je répète, cette fois la taille définie est 2.

Vous devez surveiller les changements lorsque vous mettez l'état du compte dans le deuxième argument :

  const changeValue = useCallback(() => {
    setCount(count + 1);
  }, [count]); // we watch it on every click

Maintenant, vous verrez la valeur changer chaque fois que vous cliquez sur le bouton.


A noter également : ne pas confondre le changeValue n'est pas appelé lors des clics suivants. Il appelle le useCallback à chaque fois, mais il ne met pas à jour l'état :

  const changeValue = useCallback(() => {
    console.log('clicked') // logged every time on button click
    setCount(count + 1); // count state is not being watched, 
     // setCount won't update the count on following clicks
     // once it caches the state.
  },[]); // need to watch state here to update the state

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X