recherche

Maison  >  Questions et réponses  >  le corps du texte

Comment gérer efficacement useEffect exécuté deux fois dans React ?

J'ai un compteur et useEffect 中的 console.log() 来记录我的状态中的每个更改,但是 useEffect est appelé deux fois lors du montage. J'utilise React 18. Voici le CodeSandbox de mon projet et le code ci-dessous :

import  { useState, useEffect } from "react";

const Counter = () => {
  const [count, setCount] = useState(5);

  useEffect(() => {
    console.log("rendered", count);
  }, [count]);

  return (
    <div>
      <h1> Counter </h1>
      <div> {count} </div>
      <button onClick={() => setCount(count + 1)}> click to increase </button>
    </div>
  );
};

export default Counter;

P粉759457420P粉759457420407 Il y a quelques jours796

répondre à tous(2)je répondrai

  • P粉156532706

    P粉1565327062023-10-20 11:55:03

    MISE À JOUR : Regardez cet article et soyez un peu plus sage et s'il vous plaît, ne faites pas ça.

    Utilisez ref或创建一个没有的自定义hook.

    export const useClassicEffect = createClassicEffectHook();
    
    function createClassicEffectHook() {
      if (import.meta.env.PROD) return React.useEffect;
    
      return (effect: React.EffectCallback, deps?: React.DependencyList) => {
        React.useEffect(() => {
          let isMounted = true;
          let unmount: void | (() => void);
    
          queueMicrotask(() => {
            if (isMounted) unmount = effect();
          });
    
          return () => {
            isMounted = false;
            unmount?.();
          };
        }, deps);
      };
    }

    répondre
    0
  • P粉459440991

    P粉4594409912023-10-20 09:39:10

    Depuis React 18, lorsque vous utilisez StrictMode 进行开发时,

    useEffect il est normal d'être appelé deux fois lors du montage. Voici ce qu'ils ont dans la Documentation :

    Cela peut paraître bizarre, mais au final, nous écrivons un meilleur code React en mettant en cache les requêtes HTTP et en utilisant une fonction de nettoyage lorsqu'il y a un problème entre deux appels, nous sommes sans bug, nous respectons les directives actuelles et sommes compatibles avec les versions futures. . Voici un exemple :

    /* Having a setInterval inside an useEffect: */
    
    import { useEffect, useState } from "react";
    
    const Counter = () => {
      const [count, setCount] = useState(0);
    
      useEffect(() => {
        const id = setInterval(() => setCount((count) => count + 1), 1000);
    
        /* 
           Make sure I clear the interval when the component is unmounted,
           otherwise, I get weird behavior with StrictMode, 
           helps prevent memory leak issues.
        */
        return () => clearInterval(id);
      }, []);
    
      return 
    {count}
    ; }; export default Counter;

    Dans cet article très détaillé, l'équipe React explique useEffect comme jamais auparavant et l'illustre avec des exemples :

    Pour votre cas d'utilisation spécifique, vous pouvez le laisser tel quel, pas de soucis. Et vous ne devriez pas essayer d'utiliser ces techniques avec les instructions useEffect 中的 useRefif 语句一起使用以使其触发一次,或删除 StrictMode useRef et if dans useEffect pour le déclencher une fois, ou supprimer

    StrictMode car comme vous pouvez le trouver le sur

    DocumentsuseEffect ,正如他们在 /* As a second example, an API call inside an useEffect with fetch: */ useEffect(() => { const abortController = new AbortController(); const fetchUser = async () => { try { const res = await fetch("/api/user/", { signal: abortController.signal, }); const data = await res.json(); } catch (error) { // ℹ️: The error name is "CanceledError" for Axios. if (error.name !== "AbortError") { /* Logic for non-aborted error handling goes here. */ } } }; fetchUser(); /* Abort the request as it isn't needed anymore, the component being unmounted. It helps avoid, among other things, the well-known "can't perform a React state update on an unmounted component" warning. */ return () => abortController.abort(); }, []);

    function TodoList() {
      const todos = useSomeDataFetchingLibraryWithCache(`/api/user/${userId}/todos`);
      // ...
    Si vous rencontrez toujours des problèmes, vous utilisez peut-être useEffect et comme on dit sur useEffect en premier lieu > /learn/synchronizing-with-effects#not-an-effect-initializing-the-application" rel="noreferrer">Pas un effet : initialiser l'application et

    Pas un effet : acheter le produit 🎜 , je vous recommande de lire l'🎜article 🎜Dans son ensemble. 🎜

    répondre
    0
  • Annulerrépondre