web-dev-qa-db-fra.com

Quelle est l'intention d'utiliser le crochet useCallback de React à la place de useEffect?

J'essaie de comprendre quel est le cas d'utilisation pour utiliser le crochet useCallback de React à la place du crochet useEffect .

Ils semblent tous deux agir comme un écouteur pour les changements d'état de leurs entrées (exemples tirés de React Docs ):

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

Mais, le crochet useEffect offre l'avantage supplémentaire de nettoyer les ressources là où vous auriez précédemment avec componentWillUnmount.

Alors, quel est un bon cas d'utilisation pour utiliser useCallback? Et qu'est-ce qui me manque ici?

20
Don Brody

useEffect a des aspects temporels très spécifiques qui vous sont liés ici . La fonction spécifiée sera exécutée une fois le rendu terminé et le DOM mis à jour. Cela se produira après chaque rendu où l'une des valeurs spécifiées dans le tableau du deuxième argument change.

useCallback n'exécute rien automatiquement. Il retourne une fonction qui peut être exécutée par le code nécessaire pour le déclencher. Il n'y a pas d'écoute des modifications qui provoquent une exécution du rappel. Les valeurs du tableau contrôlent simplement quelle instance de la fonction est renvoyée. Les valeurs du tableau ne contrôlent pas le moment de l'exécution de la fonction.

Un cas d'utilisation clé consiste à passer cette fonction comme accessoire à un composant enfant pour l'utiliser comme gestionnaire d'événements. useCallback vous permet de définir une fonction en ligne à utiliser comme gestionnaire d'événements (donc elle a accès à toutes les autres variables dans le contexte où la fonction est définie) sans l'inconvénient de passer un accessoire unique à l'enfant à chaque rendu . Tant que les valeurs du tableau du second argument n'ont pas changé, la même fonction sera renvoyée comme l'a été le rendu précédent. Ainsi, si le composant enfant est un composant pur, il ne sera pas forcé de restituer simplement parce qu'il reçoit toujours une fonction de gestionnaire d'événements unique.

sans useCallback

const Parent = ()=> {
   const [a, setA] = useState(null);
   const eventHandler = ()=> {
      // every render creates a unique instance of eventHandler
      // even though it always does the same thing so long as 'a' hasn't changed
      doSomethingWithA(a);
   }
   return <Child onClick={eventHandler}/>
}

avec useCallback

const Parent = ()=> {
   const [a, setA] = useState(null);
   const eventHandler = useCallback(()=> {
      // A unique function instance is passed in to useCallback on every render, but
      // eventHandler will be set to the first instance of this function
      // (i.e. potentially an instance of the function that was passed to useCallback
      // on a previous rendering) that was passed to useCallback
      // for the current value of 'a'.
      doSomethingWithA(a);
   }, [a]);
   return <Child onClick={eventHandler}/>
}

Cet article fournit un peu plus de détails que les documents React sur le cas d'utilisation de useCallback et d'autres hooks.

56
Ryan Cogswell