React: React Hook useEffect hat eine fehlende Abhängigkeit: 'xxx' ?

Erstellt am 12. Juni 2019  ·  69Kommentare  ·  Quelle: facebook/react

Hallo, ich recherchiere vor kurzem über React Hook, es ist großartig.

Aber ich habe ein Problem, ich habe in der React Hook-Dokumentation keine passende Antwort gefunden und google, um mein Problem zu lösen.

Als ich eine Funktion in useEffect und eine Funktionskomponente zusammen verwendet habe, bin ich auf eine Warnung gestoßen, dass ich keine Abhängigkeit in useEffect angegeben habe, wie unten gezeigt:

image

Gibt es eine Möglichkeit mein Problem zu lösen? Ich habe lange darüber nachgedacht.

Wie ist das aktuelle Verhalten?

React Hook useEffect has a missing dependency: 'setCenterPosition'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

Mini-Repro in Codesandbox:
https://codesandbox.io/s/trusting-kowalevski-oet4b

Irgendeine Lösung, danke.

Code

function App() {
  const [elePositionArr, setElePositionArr] = useState([
    { left: 0, top: 0 },
    { left: 0, top: 0 },
    { left: 0, top: 0 }
  ]);
  const stageRef = useRef(null);
  const Stage = useRef({ w: 0, h: 0 });
  const currentIndex = useRef(0);

  useEffect(() => {
    // Record the size of the stage
    const stageW = stageRef.current.scrollWidth;
    const stageH = stageRef.current.scrollHeight;

    Stage.current = { w: stageW, h: stageH };

    const index = Math.floor(Math.random() * 3);
    currentIndex.current = index;
    setCenterPosition(index);
  }, []);

  // Centering a block element
  function setCenterPosition(index) {
    let cacheEle = elePositionArr;
    // calc center postion
    const centerOfLeft = Stage.current.w / 2 - 25;
    const centerOfTop = Stage.current.h / 2 - 25;

    cacheEle = cacheEle.map((item, i) => {
      const randomWNum = Math.floor(Math.random() * Stage.current.w) - 50;
      const randomHNum = Math.floor(Math.random() * Stage.current.h) - 50;
      const randomLeft = randomWNum <= 50 ? 50 : randomWNum;
      const randomTop = randomHNum <= 50 ? 50 : randomHNum;
      let newItem;

      if (index === i) {
        newItem = { left: centerOfLeft, top: centerOfTop };
      } else {
        newItem = { left: randomLeft, top: randomTop };
      }

      return newItem;
    });

    setElePositionArr(cacheEle);
  }

  function handleClickLi(index) {
    if (currentIndex.current !== index) {
      setCenterPosition(index);
      currentIndex.current = index;
    }
  }

  return (
    <div className="container">
      <div className="stage" ref={stageRef}>
        {elePositionArr.map((item, index) => (
          <div className="ele" key={index} style={item}>
            {index}
          </div>
        ))}
      </div>
      <ul className="nav">
        {elePositionArr.map((item, index) => (
          <li
            className={currentIndex.current === index ? "active-li" : ""}
            onClick={() => {
              handleClickLi(index);
            }}
            key={"li" + index}
          >
            {index}
          </li>
        ))}
      </ul>
    </div>
  );
}

Hilfreichster Kommentar

Wenn Tausende von Entwicklern mit demselben Problem konfrontiert sind und das React-Entwicklerteam den Thread schließt und alle ignoriert:
8d6

Alle 69 Kommentare

Das sollte deine Frage beantworten:

https://reactjs.org/docs/hooks-faq.html#is -it-safe-to-omit-functions-from-the-list-of-dependencies

Das sollte deine Frage beantworten:

https://reactjs.org/docs/hooks-faq.html#is -it-safe-to-omit-functions-from-the-list-of-dependencies

@gaearon
Hat mein Problem nicht gelöst, mein Problem ist spezieller, mein Run functionssetElePositionArr möchte auf componentDidMount und handleClick feuern, aber die React Hook-Funktion entspricht nicht meinen Anforderungen und eine Warnung wird angezeigt.

Meine Frage ist: React Hook kann keine Funktion in der useEffect- und Funktionskomponente für die setState-Operation aufrufen.

Lassen Sie es offen, damit wir auf die zweite Frage antworten können.

Ich habe die gleiche ESLint-Warnung, aber in meinem Fall möchte ich einen asynchronen Aufruf tätigen, wenn meine Komponente bereitgestellt wird.

const ManageTagsModalBody: React.FC<IProps> = ({ children, getTags }) => {
  useEffect(() => {
    getTags();
  }, []);

  return <div>{children}</div>;
};
Line 12:  React Hook useEffect has a missing dependency: 'getTags'. Either include it or remove the dependency array. If 'getTags' changes too often, find the parent component that defines it and wrap that definition in useCallback  react-hooks/exhaustive-deps 

ManageTagsModalBody hängt nicht von irgendwelchen Daten ab, es wird nur als Wrapper verwendet, um Daten jedes Mal zu laden, wenn die Komponente gerendert wird. Es ist erwähnenswert, dass die children Komponente die Daten verwendet, die getTags abgerufen hat.

Ich bin mir nicht sicher, was ich der Liste der Abhängigkeiten hinzufügen soll.

ich bin auch an einer erklärung interessiert.
React Hook useEffect hat eine fehlende Abhängigkeit: 'dispatch'.

  useEffect(() => {
    axios.get('http://localhost:8000/api/future-registrations')
      .then((result) => {
        dispatch(initRegistrationsAction(result.data));
      });
  }, []);

Gleiches Problem hier. Seltsame Regel.

Hier gilt das gleiche. So einfach wie in https://github.com/facebook/react/issues/15865#issuecomment -506503377:

  useEffect(() => {
    dispatch(fetchPosts());
  }, []);

Gibt es eine Möglichkeit diese Warnung zu unterdrücken?

Wie in der Warnmeldung vorgeschlagen, können Sie so vorgehen

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

@fayway Wenn sich initFetch und der Dispatch-Wert ändern, wird der Callback von useEffect ausgeführt.
er möchte einmal callback ausführen

@shkyung In meinem Fall ändert sich Versand auch nicht

Vielleicht kann es so sein

const setCenterPosition = useRef(null)
setCenterPosition.current = useCallback( ()=>{} ,[deps])

effect(()=>{ setCenterPosition.current() },[setCenterPosition,otherDeps])

Diese Änderung scheint ein bisschen lächerlich und kontraproduktiv, um ehrlich zu sein. Rollback lieber auf eine frühere Version zurück und lassen Sie diese durchdenken.

Habe das gleiche Problem. Ich möchte nur, dass mein Abruf auf componentDidMount ausgelöst wird. Das Hinzufügen der Abhängigkeit zum Array führt dazu, dass der Endpunkt wiederholt erreicht wird.

React Hook useEffect hat eine fehlende Abhängigkeit: 'dispatch'.

const [state, dispatch] = useReducer(reducer, initialState);
const { count, step } = state;

useEffect(() => {
  const id = setInterval(() => {
    dispatch({ type: 'tick' }); // Instead of setCount(c => c + step);
  }, 1000);
  return () => clearInterval(id);
}, [dispatch]);

Dies scheint ein recht häufiger Anwendungsfall zu sein - einer, auf den ich bei meinem aktuellen Projekt gestoßen bin.

Sie möchten einen Effekt-Hook nur einmal ausführen, aber es GIBT eine Abhängigkeit, obwohl Sie sich nur um den Status beim Start kümmern. Verwendet derzeit
// eslint-disable-next-line react-hooks/exhaustive-deps ,
um die Linting-Regel auszuschalten, wäre aber in diesem Fall schön, dies nicht zu tun.

Dies scheint ein recht häufiger Anwendungsfall zu sein - einer, auf den ich bei meinem aktuellen Projekt gestoßen bin.

Sie möchten einen Effekt-Hook nur einmal ausführen, aber es GIBT eine Abhängigkeit, obwohl Sie sich nur um den Status beim Start kümmern. Verwendet derzeit
// eslint-disable-next-line react-hooks/exhaustive-deps ,
um die Linting-Regel auszuschalten, wäre aber in diesem Fall schön, dies nicht zu tun.

Das Schließen von Lint ist nur eine vorübergehende Lösung, der Schlüssel zu diesem Problem reicht nicht aus, um den Haken zu verstehen.

Gleiches Problem hier. Ich wollte nur einmal eine Funktion in useEffect() auslösen, wobei [] als zweiter Parameter das tut, was ich will, aber es gibt diese Warnung immer wieder aus.

So eine seltsame Warnung, weil ich sie bis heute bei einem neuen Projekt noch nie gesehen habe. Es ruiniert den Anwendungsfall, dass etwas nur einmal aufgerufen wird, wenn die Komponente montiert wurde. Es scheint keinen Workaround zu geben, außer die Fusselwarnung zu ignorieren.

Ich würde gerne meine zwei Cent hier reinstecken. Insbesondere bei der Verwendung von Axios zum Abbrechen einer Netzwerkanfrage. Werde bei Bedarf ein separates Problem erstellen, fühlte mich jedoch direkt von diesem Problem betroffen. Mein useApi-Hook ist also wie folgt -

import axios, { AxiosInstance } from "axios";
import axiosRetry from "axios-retry";
import { FetchEnv } from "../../utilities";
import { useStorage } from "../useStorage";

export const useApi = ({ isAuth = false, retries = 3 } = {}) => {
  const cancelToken = axios.CancelToken.source();
  const { getItem } = useStorage();

  const getBaseUrl = () => {
    return FetchEnv({
      defaultValue: "http://api.example.com",
      key: "API_URI"
    });
  };

  const authorizedClient = (client: AxiosInstance) => {
    const session = getItem("SESSION", "sessionStorage");
    const hasAccessToken = Boolean(session.tokens.accessToken);

    if (isAuth && !hasAccessToken) {
      console.error("No access token found to initiate authorized request.");
      return client;
    } else {
      client.defaults.headers[
        "Authorization"
      ] = `Bearer ${session.tokens.accessToken}`;
      return client;
    }
  };

  const buildFetch = (): AxiosInstance => {
    const client = axios.create({
      baseURL: getBaseUrl(),
      cancelToken: cancelToken.token
    });
    axiosRetry(client, { retries });
    return isAuth ? authorizedClient(client) : client;
  };

  return {
    cancelRequest: cancelToken.cancel,
    fetch: buildFetch()
  };
};

Um diesen Hook innerhalb einer Komponente zu verwenden, definieren Sie ihn einfach wie folgt, dann kann er verwendet werden, um sowohl authentifizierte als auch nicht authentifizierte Aufrufe entweder beim Mounten, innerhalb eines useEffect, als Teil eines Event-Handlers usw. durchzuführen die mit der Axios-Instanz "fetch" relativ zu dieser Komponente gepaart ist.

const { cancelRequest, fetch } = useApi();

Wenn diese Komponente aus irgendeinem Grund abgebaut wird, wird Folgendes aufgerufen:

  useEffect(() => {
    return () => {
      cancelRequest("Auth network request cancelled");
    };
  }, []);

Jetzt funktioniert es zur Zeit einwandfrei. Wenn die Warnung jedoch angewendet wird (indem CancelRequest als useEffect-Abhängigkeit verwendet wird), LÖScht die Netzwerkanforderung sofort ab, wenn die fetch-Methode aufgerufen wird. Jeder Rat wäre sehr dankbar, aber es scheint, dass die einzige Lösung derzeit darin besteht, ts-lint diese Vorgehensweise zu deaktivieren ...

Ich denke, das Problem hier könnte die Art sein, wie wir über Hooks denken. Der Kommentar von @luojinghui deutet darauf hin, dass mehr denkt . Vielleicht müssen wir anders denken? Ich konnte dieses Problem in einem meiner Hooks mit etwas Refactoring beseitigen. Dadurch ist der Code übersichtlicher.

Es führte mich zu der Frage , ob der Timing-Code im Beispiel von @ Stoner609 direkt darüber in einem useCallback-Hook sein sollte? Es ist jedoch immer noch seltsam, eine Funktion (die statisch sein sollte) als Abhängigkeit zu haben.

Ich denke, dieser Fall sollte eine Ausnahme sein

Wenn Sie eine Funktion nur einmal ausführen möchten, wenn die Komponente geladen wird und die Parameter aufnimmt, können Sie useRef verwenden, um die Warnung zu vermeiden. So etwas funktioniert:

  const InitialPropA= useRef(propA);
  useEffect(() => {
    myFunction(InitialPropA.current);
  }, [myFunction, InitialPropA]);

Wie in der Warnmeldung vorgeschlagen, können Sie so vorgehen

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

So sehr ich diese witzige Antwort liebe, geschieht dies normalerweise in meinem Code.
Ich möchte nicht all diese nervigen Warnungen vor dem Verschwinden des Versands haben.

Ich würde gerne genau wissen, was und warum in dieser Reihe von Mysterien passiert :)

Wie in der Warnmeldung vorgeschlagen, können Sie so vorgehen

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

Dies kann im Falle einer API auch zu einem Speicherleck führen, es wird den Aufruf in einer Endlosschleife durchführen.

Brauche dafür wirklich einen Fix. Es gibt mir immer wieder Fehler und keine Ideen, wie ich es lösen kann, wenn Sie eine Funktion in useEffect() nur einmal auslösen möchten.

Stehe vor dem gleichen Fehler -

React Hook useEffect hat eine fehlende Abhängigkeit: 'props'. 'props' ändert sich jedoch, wenn sich eine Requisite ändert, daher besteht die bevorzugte Lösung darin, das 'props'-Objekt außerhalb des useEffect-Aufrufs zu destrukturieren und auf diese spezifischen Requisiten innerhalb von useEffect React-Hooks/Exhaustive-Deps zu verweisen

Code -

  useEffect(() => {
    props.dispatch(searchMediaAction("rain"));
  }, []);

@luojinghui : Lass es mich wissen, wenn du den

gleicher Fehler

gleiches Problem. Ich möchte das Verhalten von componentDidMount nachahmen; Die Warnung interessiert mich nicht; Ich möchte den Hook nicht erneut ausführen, wenn sich etwas ändert

Ich würde vorschlagen, diese Warnung nicht anzuzeigen, wenn das zweite Argument für useEffect() [] , b/c in diesem Fall weiß der Entwickler, dass dieser Effekt nur einmal ausgeführt wird und daher _will_ verwendet die anfänglichen Requisitenwerte und es ist egal, ob sich die Requisite bei nachfolgenden Renderings ändert.

Fall 1:
Wenn wir möchten, dass die Funktion sowohl bei der Initialisierung als auch bei einer Wertänderung der angegebenen Parameter ausgeführt wird (wie die lint-Warnung nahelegt), übergeben wir diese Parameter an das Array.

Fall 2:
Wenn die Funktion bei der Initialisierung genau einmal ausgeführt werden soll , verwenden wir ein leeres Array, damit der Effekt nur einmal ausgelöst wird.

In Fall 2 lauschen wir im Wesentlichen auf das Ereignis componentDidMount gemäß den Dokumentationsspezifikationen von React Hook. Der Lint-Fehler stimmt nicht mit der React Hook-Dokumentation und den Erwartungen der Entwickler überein.

Warum ist das geschlossen?

Irgendwelche Lösungen?

@kennylbj

Nachdem ich eine Reihe verschiedener Vorschläge ausprobiert habe, hat dies letztendlich für mich funktioniert. Ich zog es vor, eslint-disable nicht zu verwenden, während ich versuchte, den Code für einen Neuling relativ einfach zu halten. Dieser Ansatz ermöglicht es Ihnen, Ihre Dispatch-Funktion zu übergeben, ohne sie innerhalb von useCallback aufzurufen. Hoffe das hilft.

```javascript
// ... innerhalb der Funktionskomponente
const {dispatchFunc} = customHook();
const memoizeDispatchFunc = useCallback(dispatchFunc, []);

useEffect(() => {
memoizeDispatchFunc();
}, [memoizeDispatchFunc]);
````

Können wir einfach das leere Array entfernen? Dies scheint zu funktionieren (der Code läuft immer noch wie erwartet und die Warnung ist verschwunden), aber ich weiß nicht, ob es einen Grund gibt, warum wir es nicht so machen sollten.

useEffect(()=>{ myFunc(); } )

@robthedev Tolle Lösung.
Wir können den Code sogar vereinfachen, wenn wir redux verwenden:

const dispatch = useDispatch();

// redux can guarantee that the dispatch function will not change between renders.
// so we don't need to wrap it with useCallback for now.
useEffect(() => {
  dispatch(actions());
}, [dispatch]);

Dans dieser Artikel hilft mir sehr.

Die Lösung für dieses Problem besteht nicht darin, eine Abhängigkeit zu entfernen, sondern wir können Funktionen hochheben, die keine Requisiten oder Zustände außerhalb der Komponente benötigen, oder sie in useCallback einschließen, wo sie definiert sind.

@kennylbj

Nachdem ich eine Reihe verschiedener Vorschläge ausprobiert habe, hat dies letztendlich für mich funktioniert. Ich zog es vor, eslint-disable nicht zu verwenden, während ich versuchte, den Code für einen Neuling relativ einfach zu halten. Dieser Ansatz ermöglicht es Ihnen, Ihre Dispatch-Funktion zu übergeben, ohne sie innerhalb von useCallback aufzurufen. Hoffe das hilft.

// ... inside function component
const { dispatchFunc } = customHook();
const memoizeDispatchFunc = useCallback(dispatchFunc, []);

useEffect(() => {
  memoizeDispatchFunc();
}, [memoizeDispatchFunc]);

Bei mir funktioniert das obige Beispiel nicht.

Bekomme diesen Fehler:
TypeError: Cannot destructure property 'dispatchFunc' of 'componentDidMount(...)' as it is undefined.

@react-team: Happy Boilerplate Code. :) Kann es bitte wieder logisch und lesbar sein... Ereignisse sollten einfach zu verwenden sein... ohne 5+ Zeilen Logik schreiben zu müssen, nur um eine Funktion aufzurufen.

Bei mir trat der Fehler in folgender Situation auf:

  useEffect(() => {
    props.getTasks()
  }, [])

Ich habe es so korrigiert:

const { getTasks } = props
  useEffect(() => {
    getTasks()
  }, [getTasks])

Wenn Tausende von Entwicklern mit demselben Problem konfrontiert sind und das React-Entwicklerteam den Thread schließt und alle ignoriert:
8d6

Mein Problem war anders als bei anderen in diesem Thread, also werde ich es teilen, falls eine andere arme Seele in den Kaninchenbau geht. Ich war gerade 1 1/2 Stunden unten

function hydrate( _state, _errors=false) {
    console.log('hydrate()');
    setState({...state,..._state});
    if(_errors){
        setErrors({...errors,..._errors});
    }
}

vom Benutzer wird erwartet, dass er dies mit useEffect() um seinen Zustand wie folgt zu hydratisieren:

useEffect(()=>{
    hydrate({
        name:'Garrett',
        email:'[email protected]',
        newsletter: 'yes'
    });
},[hydrate]); //unfortunately, this causes an infinite render, because hydrate will always change

Um dies zu lösen, habe ich gerade meine Hydrate-Funktion so geändert, dass sie in useCallback() verpackt ist wird dies für alle meine Hilfsfunktionen implementieren, die von meinem benutzerdefinierten Hook zurückgegeben werden.

const hydrate = useCallback(( _state, _errors=false )=> {
    console.log('hydrate()');
    setState({...state,..._state});
    if(_errors){
        setErrors({...errors,..._errors});
    }
},[]);

kann jemand bestätigen, ob dies wahr ist, useCallback verhindert, dass hydrate im Render mutiert wird, und daher ist es wahrscheinlich besser, alle diese Funktionen für eine bessere Leistung in useCallback einzuschließen ?

redux can guarantee that the dispatch function will not change between renders.

Bist du dir da sicher?
Link zu den Dokumenten, wo es so steht, bitte.

Weitere Informationen finden Sie unter https://overreacted.io/a-complete-guide-to-useeffect/#decoupling -updates-from-actions oder im useEffect-Quellcode nach Implementierungsdetails.

Hier beziehe ich mich nur auf das, was Dan sagte:

Die Antwort ist, dass React garantiert, dass die Dispatch-Funktion über die gesamte Lebensdauer der Komponente konstant bleibt. Das obige Beispiel muss das Intervall also nie neu abonnieren.

garantiert eine konstante Versandfunktion

Cool, danke!

Wenn Tausende von Entwicklern mit demselben Problem konfrontiert sind und das React-Entwicklerteam den Thread schließt und alle ignoriert:
8d6

So ziemlich das. Hier probiere ich Hooks aus und werde mit dieser Warnung begrüßt, die keinen Sinn macht und in keinem der offiziellen Dokumente behandelt wird. Sie fragen sich wirklich, ob Hooks für ernsthafte Arbeit bereit sind, wenn ein einfacher Anwendungsfall wie "Bitte führen Sie diesen Effekt nur einmal aus" so viel Mühe bereiten.

Naja, mehr gibt es nicht zu sagen, außer dass der Thread smh geschlossen ist.

Steht vor dem gleichen Problem!

LÖSUNG,
(das hat bei mir funktioniert):

const onInit = function(){ 
    console.log('initiated', Date.now());
}

useEffect(onInit, []);

Ich würde es vorziehen, das Problem auf der Fusselseite zu beheben, aber hey ...

@ ra30r nette

Immer noch nichts? 😔

Ich hatte einen Fall, in dem ich in einem Kurs zu Udemy gelernt habe, Fehler bei der Formularvalidierung auszulösen.

Dies löste die fehlende Abhängigkeit "Versand" aus, funktionierte aber trotzdem:

  useEffect(() => {
    if (state.business_name.value) {
      const delay = setTimeout(() => dispatch({ type: "businessNameAfterDelay" }), 1000)
      return () => clearTimeout(delay)
    }
  }, [state.business_name.value])

Anhand des Beispiels von @ra30r habe ich es folgendermaßen geändert, um den Fehler zu löschen:

  const businessNameAfterDelay = function () {
    if (state.business_name.value) {
      const delay = setTimeout(() => dispatch({ type: "businessNameAfterDelay" }), 1000)
      return () => clearTimeout(delay)
    }
  }

  useEffect(businessNameAfterDelay, [state.business_name.value])

Warum ist das geschlossen?

Ich glaube, irgendwo wurde eine Antwort gegeben.. lol.. sowieso.. die Lösung ist so:
useEffect(() => { dispatch(); }, [dispatch]);

hoffe das hilft!!

Warum ist das geschlossen?

Ich glaube, irgendwo wurde eine Antwort gegeben.. lol.. sowieso.. die Lösung ist so:
useEffect(() => { dispatch(); }, [dispatch]);

hoffe das hilft!!

Ja, dieser Workaround funktioniert, sagte @kennylbj hier vor einiger Zeit.
Warum ist das Thema geschlossen? Es gibt hier auch Memes dazu... xd

Mein Problem sieht ungefähr so ​​aus (Beispielcode):

  const [userStatus, setUserStatus]: any = React.useState([]);
  const [userData, setUserData]: any = React.useState([]);

  useEffect(() => {
    setUserStatus(!userStatus);
    return () => {};
  }, [userData]);

Wie im Code möchten Sie den Wert von userStatus ändern, wenn sich userData ändert. Wenn Sie in diesem Fall den Wert von userStatus überprüfen möchten, müssen Sie ihn zu deps hinzufügen:

  const [userStatus, setUserStatus]: any = React.useState([]);
  const [userData, setUserData]: any = React.useState([]);

  useEffect(() => {
    setUserStatus(!userStatus);
    return () => {};
  }, [userData, userStatus]);

In diesem Szenario wird es eine endlose Schleife sein

@spmsupun
Sie können den Callback-Stil von useState verwenden, um die Einführung der userStatus-Variable in das Abhängigkeits-Array von useEffect zu vermeiden.

 useEffect(() => {
    setUserStatus(prevState => !prevState);
    return () => {};
  }, [userData]);

Und das sind sogenannte funktionale Updates .

Lösung --> fügen Sie einfach den Versand als letztes für die Abhängigkeit hinzu
React Hook useEffect hat eine fehlende Abhängigkeit: 'dispatch'.

  useEffect(() => {
    axios.get('http://localhost:8000/api/future-registrations')
      .then((result) => {
        dispatch(initRegistrationsAction(result.data));
      });
**  }, [dispatch]);**

@kennylbj Das ist gut, wenn Sie sich mit einem Staat befassen, mein tatsächliches Szenario sind Requisiten. Ich sende Requisiten von Parent und es ändert sich zweimal, sodass usereffect zweimal aufruft, aber ich führe einen Listener darin aus und er hört zweimal zu.

@spmsupun Aber ich denke, es ist ganz normal, den vorherigen Listener

Wenn Sie immer noch nicht möchten, dass der Listener zweimal aufgerufen wird, sollten Sie meiner Meinung nach mehr auf die ihm übergebenen Requisiten achten und sicherstellen, dass sie während des Renderns nicht geändert werden.

@kennylbj Nun, ich
image
Ich schätze, ich muss das von der Listener-Klasse aus handhaben,

Scheint, als ob Ihr Listener zweimal aufgerufen wird, auch wenn die Socket-ID gleich ist.

Ich glaube nicht, dass dies passieren wird, wenn die folgende Situation eintritt:

ts // call useEffect if and only if sockeId changed. useEffect(() => { const unregister = register(socketId); return () => unregister(socketId); }, [socketId])

Gibt es andere Variablen im Dependencies-Array, die während verschiedener Renderings geändert wurden und dieses Verhalten verursachen?

Ja, 3 Abhängigkeiten, aber ich finde es anders heraus

Pien

Wie in der Warnmeldung vorgeschlagen, können Sie so vorgehen

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

wow,非常感谢你🙏

🚀 Der folgende Codeausschnitt funktioniert bei mir wirklich gut

Auf Komponente wurde gemountet

const onInit = () => getUsers()
useEffect(onInit, [])

Bei Parameteränderung

const onInit = () => getUser(id)
useEffect(onInit, [id])

Beste Problemumgehung: React-Hooks/Exhaustive-Deps: "off"
Ich habe diese Eslint-Funktion nie als nützlich empfunden. Je.

🚀 Der folgende Codeausschnitt funktioniert bei mir wirklich gut

Auf Komponente wurde gemountet

const onInit = () => getUsers()
useEffect(onInit, [])

Bei Parameteränderung

const onInit = () => getUser(id)
useEffect(onInit, [id])

gute Arbeit.

Ich glaube nicht, dass die Reaktionsdokumente den Anwendungsfall von @luojinghui vollständig abdecken, das ist auch dasselbe, das ich habe:

Wir haben mehrere Möglichkeiten, eine gegebene Funktion aufzurufen, zB: setCenterPosition() . Es könnte aufgerufen werden, indem auf Zustandsänderungen (angeschlossen über useEffect ), ein Click-Handler (direkt aufgerufen) usw.

Die Reaktionsdokumente schlagen vor

Aus diesem Grund möchten Sie normalerweise Funktionen deklarieren, die von einem darin enthaltenen Effekt benötigt werden

Aber normalerweise müssen wir in realen Beispielen Funktionen wiederverwenden, wie wir es normalerweise mit Instanzmethoden für eine Klassenkomponente ( this.setCenterPosition(...) ) tun würden, und ich frage mich langsam, ob Hooks tatsächlich gut für funktionsreiche, komplexe Komponenten.

Ich bin mir nicht sicher, aber vielleicht ist die Lösung useCallback

const setCenterPosition = useCallback(() => {
  ...
}, [Stage, elePositionArr, setElePositionArr]);

useEffect() => {
  ...
}, [stageRef, Stage, currentIndex, setCenterPosition]);

...aber das finde ich irgendwie ekelhaft und ich hoffe, es gibt einen saubereren Weg. Vielleicht kann @gaearon das bestätigen?

vor dem gleichen Problem kann ich den Warnbus mit dieser Zeile am Ende von useEffect // eslint-disable-next-line react-hooks/exhaustive-deps deaktivieren, aber ich möchte ihn nicht verwenden

Hier ist mein Code

`const [items, setItems] = useState([
{
Name: "Test 1",
ID: 1
},
{
Name: "Test 2",
ID: 2
},
{
Name: "Test 3",
ID: 3
},
{
Name: "Test 4",
ID: 4
},
{
Name: "Test 5",
ID: 5
}
]);

useEffect(() => {
const intervalId = setInterval(() => {
setItems (shuffleArray (Elemente));
}, 1000);
zurück () => {
clearInterval(intervalId);
};
// eslint-disable-next-line-react-hooks/exhaustive-deps
}, []);

Meine Lösung für dieses Problem bestand darin, in diesen Fällen einfach die Verwendung von React Hooks einzustellen. Wenn Ihre Komponente sehr viel Zustandslogik und Lebenszyklusereignisse wie componentDidMount , verwenden Sie einfach eine Klassenkomponente und sparen Sie sich die Kopfschmerzen. Klassenkomponenten sind völlig in Ordnung, und wenn dieser Thread etwas beweist, dann ist es, dass React Hooks nicht bereit sind, sie vollständig zu ersetzen, wenn komplexe Zustandslogik oder Lebenszyklusereignisse erforderlich sind (und in den meisten Fällen auch keinen Vorteil bieten - ist Ihr Code _wirklich_ so viel besser für die Verwendung von React Hooks?).

Ich werde meine eigene Verwendung von React Hooks auf einfache wie useState , um boolesche Flags und dergleichen zu setzen. Wenn eine Komponente jemals komplex genug wird, um useEffect zu benötigen, betrachte ich das als ein Zeichen dafür, dass eine Klassenkomponente vielleicht einfach besser passt.

(Der Übersichtlichkeit halber bearbeitet).

Das ist meine Lösung vorerst:

const mounted = () => {
  dispatch(something());
}

useEffect(mounted, []);

Danke @ra30r reagiere/issues/15865#issuecomment-651254164

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen