React: React Hook useEffect a une dépendance manquante : 'xxx' ?

Créé le 12 juin 2019  ·  69Commentaires  ·  Source: facebook/react

Salut, je fais des recherches sur React Hook récemment, c'est génial.

Mais j'ai un problème, je n'ai pas trouvé de réponse appropriée dans la documentation de React Hook et google pour résoudre mon problème.

Lorsque j'ai utilisé une fonction dans useEffect et un composant de fonction ensemble, j'ai rencontré un avertissement indiquant que je n'avais pas spécifié de dépendance dans useEffect, comme indiqué ci-dessous :

image

Y a-t-il un moyen de résoudre mon problème ? J'y pense depuis longtemps.

Quel est le comportement actuel ?

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

Mini repro dans codesandbox :
https://codesandbox.io/s/trusting-kowalevski-oet4b

Toute solution, merci.

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

Commentaire le plus utile

Lorsque des milliers de développeurs sont confrontés au même problème et que l'équipe de développement de React ferme le fil et ignore tout le monde :
8d6

Tous les 69 commentaires

Ceci devrait répondre à votre question:

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

Ceci devrait répondre à votre question:

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

@gaearon
N'a pas résolu mon problème, mon problème est plus spécial, mon run functionsetElePositionArr veut se déclencher sur componentDidMount et handleClick, mais la fonction React Hook ne répond pas à mes exigences et un avertissement apparaît.

Ma question est : React Hook ne peut pas appeler une fonction dans le composant useEffect et function pour l'opération setState?

Laisser ouvert afin que nous puissions répondre à la deuxième question.

J'ai le même avertissement ESLint mais dans mon cas, je souhaite effectuer un appel asynchrone lorsque mon composant est monté.

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 ne dépend d'aucune donnée, il est uniquement utilisé comme enveloppe pour charger des données à chaque fois que le composant est rendu. Il convient de noter que le composant children utilise les données que getTags a récupérées.

Je ne sais pas quoi ajouter à la liste des dépendances.

Je suis également intéressé pour une explication.
React Hook useEffect a une dépendance manquante : 'dispatch'.

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

Même problème ici. Règle étrange.

Pareil ici. Aussi simple que dans https://github.com/facebook/react/issues/15865#issuecomment -506503377 :

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

Existe-t-il un moyen de supprimer cet avertissement ?

Comme suggéré dans le message d'avertissement, vous pouvez faire comme ça

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

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

@fayway puis chaque fois que initFetch et la valeur de répartition sont modifiés, le rappel de useEffect sera exécuté.
il veut exécuter le rappel une fois

@shkyung Dans mon cas, initFetch ne changera pas la cause (magasin.) L' expédition ne change pas non plus

Peut-être que ça peut être comme ça

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

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

Ce changement semble un peu ridicule et contre-productif pour être tout à fait franc. Revenez plutôt à une version antérieure et laissez-vous réfléchir à celle-ci.

Avoir le même problème. Je veux seulement que mon fetch se déclenche sur componentDidMount. L'ajout de la dépendance au tableau entraîne l'atteinte répétée du point de terminaison.

React Hook useEffect a une dépendance manquante : '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]);

Cela semble être un cas d'utilisation assez courant - celui que j'ai rencontré sur mon projet actuel.

Vous voulez exécuter un hook d'effet une seule fois, mais il y A une dépendance, bien que vous ne vous souciez que de l'état de celui-ci au démarrage. Utilise actuellement
// eslint-disable-next-line react-hooks/exhaustive-deps ,
pour désactiver la règle de peluchage mais ce serait bien de ne pas avoir à le faire dans ce cas.

Cela semble être un cas d'utilisation assez courant - celui que j'ai rencontré sur mon projet actuel.

Vous voulez exécuter un hook d'effet une seule fois, mais il y A une dépendance, bien que vous ne vous souciez que de l'état de celui-ci au démarrage. Utilise actuellement
// eslint-disable-next-line react-hooks/exhaustive-deps ,
pour désactiver la règle de peluchage mais ce serait bien de ne pas avoir à le faire dans ce cas.

La fermeture de Lint n'est qu'une solution temporaire, la clé de ce problème n'est pas suffisante pour comprendre l'hameçon.

Même problème ici. Je voulais juste déclencher une fonction dans useEffect() une fois, avoir [] comme deuxième paramètre fait ce que je veux, mais il continue à donner cet avertissement.

Un avertissement si étrange parce que je ne l'ai jamais vu jusqu'à aujourd'hui sur un nouveau projet. Cela ruine le cas d'utilisation d'avoir quelque chose appelé une seule fois lorsque le composant est monté. Il ne semble pas y avoir de solution de contournement, sauf en ignorant l'avertissement de peluches.

J'aimerais mettre mes deux cents ici. En particulier avec l'utilisation d'Axios pour annuler une requête réseau. Je créerai un problème distinct si nécessaire, mais je pense que ce problème m'affecte directement. Donc, mon crochet useApi est le suivant -

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()
  };
};

Pour utiliser ce hook dans un composant, définissez-le simplement comme ci-dessous, puis il peut être utilisé pour effectuer des appels authentifiés et non authentifiés soit sur le montage, dans un useEffect, dans le cadre d'un gestionnaire d'événements, etc. cancelRequest est le jeton d'annulation unique généré qui est associé à l'instance axios "fetch" relative à ce composant.

const { cancelRequest, fetch } = useApi();

Si, pour une raison quelconque, ce composant se démonte, la commande suivante est appelée :

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

Maintenant, cela fonctionne parfaitement à l'heure actuelle. Cependant, l'avertissement, lorsqu'il est appliqué (en mettant cancelRequest en tant que dépendance useEffect) ANNULE immédiatement la demande réseau lorsque la méthode fetch est appelée. Tout conseil serait grandement apprécié, mais il semblerait que la seule solution à l'heure actuelle soit de désactiver ts-lint pour aller de l'avant...

Je pense que le problème ici peut être la façon dont nous pensons aux crochets. Le commentaire de @luojinghui suggère qu'il y a plus à cela qu'il n'y

Il m'a conduit à se demander si, dans le @ de exemple juste au- dessus cela, le code temporel doit être dans un crochet useCallback? Il est quand même étrange d'avoir une fonction (qui devrait être statique) en tant que dépendance.

Je pense que ce cas devrait être une sorte d'exception

Si vous souhaitez exécuter une fonction une seule fois lorsque le composant se charge et qui prend des paramètres, vous pouvez utiliser useRef pour éviter l'avertissement. Quelque chose comme ça marche :

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

Comme suggéré dans le message d'avertissement, vous pouvez faire comme ça

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

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

Autant j'aime cette réponse pleine d'esprit, c'est généralement ce qui se passe dans mon code.
Je ne veux pas avoir tous ces avertissements embêtants sur la disparition d'une expédition.

J'aimerais savoir exactement ce qui se passe et pourquoi dans ce tableau de mystère :)

Comme suggéré dans le message d'avertissement, vous pouvez faire comme ça

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

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

cela peut également créer une fuite de mémoire dans le cas de quelque chose comme une API, il fera l'appel sur une boucle infinie.

Vraiment besoin d'un correctif pour cela. Il continue de me donner des erreurs et aucune idée de comment le résoudre si vous voulez déclencher une fonction à l'intérieur de useEffect() juste une fois.

Face à la même erreur -

React Hook useEffect a une dépendance manquante : 'props'. Cependant, 'props' changera lorsque n'importe quel accessoire changera, donc le correctif préféré est de déstructurer l'objet 'props' en dehors de l'appel useEffect et de se référer à ces accessoires spécifiques à l'intérieur de useEffect react-hooks/exhaustive-deps

Code -

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

@luojinghui : Faites-moi savoir si vous avez résolu l'erreur de charpie

même erreur

même problème. Je veux imiter le comportement de componentDidMount ; Je ne suis pas intéressé par l'avertissement ; Je ne veux pas relancer le crochet quand quelque chose change

Je proposerais de ne pas afficher cet avertissement lorsque le deuxième argument de useEffect() est [] , b/c dans ce cas, le développeur sait que cet effet ne va s'exécuter qu'une seule fois et donc _veut_ utiliser les valeurs initiales de l'accessoire et ne se soucie pas si l'accessoire change lors des rendus suivants.

Cas 1:
Si nous voulons que la fonction s'exécute lors de l'initialisation ainsi que lorsque la valeur des paramètres spécifiés change (comme le suggère l'avertissement de lint), alors nous passons ces paramètres dans le tableau.

Cas 2 :
Si nous voulons que la fonction s'exécute exactement une fois lors de l'initialisation , nous utilisons un tableau vide pour que cet effet ne soit déclenché qu'une seule fois.

Dans le cas 2, nous écoutons essentiellement l'événement componentDidMount conformément aux spécifications de la documentation de React Hook. L'erreur de charpie est incompatible avec la documentation de React Hook et les attentes des développeurs.

Pourquoi est-ce fermé ?

Des solutions ?

@kennylbj

Après avoir essayé un tas de suggestions différentes, c'est ce qui a finalement fonctionné pour moi. J'ai préféré ne pas utiliser eslint-disable, tout en essayant de garder le code relativement simple pour un débutant. Cette approche vous permet de transmettre votre fonction de répartition sans l'invoquer dans useCallback. J'espère que cela t'aides.

```javascript
// ... à l'intérieur du composant de fonction
const { dispatchFunc } = customHook();
const memoizeDispatchFunc = useCallback(dispatchFunc, []);

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

Pouvons-nous simplement supprimer le tableau vide ? Cela semble fonctionner (le code fonctionne toujours comme prévu et l'avertissement a disparu), mais je ne sais pas s'il y a une raison pour laquelle nous ne devrions pas le faire de cette façon.

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

@robthedev Excellente solution.
On peut même simplifier le code si on utilise redux :

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

Cet article de Dan m'aide beaucoup.

La solution à ce problème n'est pas de supprimer une dépendance, à la place, nous pouvons lever des fonctions qui n'ont pas besoin d'accessoires ou d'état en dehors du composant ou les envelopper dans useCallback où elles sont définies.

@kennylbj

Après avoir essayé un tas de suggestions différentes, c'est ce qui a finalement fonctionné pour moi. J'ai préféré ne pas utiliser eslint-disable, tout en essayant de garder le code relativement simple pour un débutant. Cette approche vous permet de transmettre votre fonction de répartition sans l'invoquer dans useCallback. J'espère que cela t'aides.

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

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

Avec moi, l'exemple ci-dessus ne fonctionne pas.

Obtenez cette erreur :
TypeError: Cannot destructure property 'dispatchFunc' of 'componentDidMount(...)' as it is undefined.

@react-team : Code de passe-partout heureux. :) Peut-il être à nouveau logique et lisible... les événements devraient être simples à utiliser... sans avoir à écrire plus de 5 lignes de logique juste pour appeler une fonction.

Pour moi, l'erreur est apparue dans la situation suivante:

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

Je l'ai corrigé comme ceci :

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

Lorsque des milliers de développeurs sont confrontés au même problème et que l'équipe de développement de React ferme le fil et ignore tout le monde :
8d6

mon problème était différent des autres dans ce fil, donc je le partagerai au cas où une autre pauvre âme descendrait dans le terrier du lapin, je viens d'être en panne depuis 1 heure et demie

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

l'utilisateur est censé l'utiliser avec useEffect() afin d'hydrater son état comme suit :

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

donc pour résoudre ce problème, j'ai juste changé ma fonction hydrate pour qu'elle soit enveloppée dans useCallback() , maintenant elle n'est pas mutée à chaque rendu (je suppose), et c'est censé être mieux pour les performances, ce qui si cela s'avère vrai je l'implémentera pour toutes mes fonctions d'assistance renvoyées par mon hook personnalisé.

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

quelqu'un peut-il confirmer si cela est vrai, useCallback empêche hydrate d'être muté dans le rendu, et il est donc probablement préférable d'envelopper toutes ces fonctions dans useCallback pour de meilleures performances ?

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

Êtes-vous sûr de cela?
Lien vers les documents où il est dit s'il vous plaît.

Consultez https://overreacted.io/a-complete-guide-to-useeffect/#decoupling -updates-from-actions pour plus de détails ou vous pouvez consulter le code source useEffect pour les détails de mise en œuvre.

Ici, je fais juste référence à ce que Dan a dit :

La réponse est que React garantit que la fonction de répartition est constante tout au long de la durée de vie du composant. Ainsi, l'exemple ci-dessus n'a jamais besoin de réinscrire l'intervalle.

garantit que la fonction de répartition est constante

Cool merci!

Lorsque des milliers de développeurs sont confrontés au même problème et que l'équipe de développement de React ferme le fil et ignore tout le monde :
8d6

À peu près ça. Ici, j'essaie les crochets et je suis accueilli par cet avertissement qui n'a aucun sens et n'est couvert dans aucun des documents officiels. On se demande vraiment si les hooks sont prêts pour un travail sérieux alors qu'un cas d'utilisation de base comme "s'il vous plaît n'exécutez cet effet qu'une seule fois" donne autant de problèmes.

Bon, pas grand chose d'autre à dire, à part le fait que le fil soit fermé smh.

Face au même problème !

SOLUTION,
(ça a marché pour moi) :

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

useEffect(onInit, []);

Je préférerais que le problème soit résolu du côté des peluches, mais bon...

@ ra30r belle solution de contournement mais vous vous demandez si cela peut créer des effets secondaires ? :pensée:

Toujours rien? ??

J'ai eu un cas où j'ai appris à déclencher des erreurs de validation de formulaire à partir d'un cours sur Udemy.

Cela a déclenché la dépendance manquante "dispatch", mais a toujours fonctionné :

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

En utilisant l'exemple de @ ra30r , je l'ai changé pour effacer l'erreur :

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

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

Pourquoi est-ce fermé ?

Je crois qu'une réponse a été donnée quelque part.. lol.. de toute façon.. la solution est de faire comme ceci :
useEffect(() => { dispatch(); }, [dispatch]);

J'espère que cela t'aides!!

Pourquoi est-ce fermé ?

Je crois qu'une réponse a été donnée quelque part.. lol.. de toute façon.. la solution est de faire comme ceci :
useEffect(() => { dispatch(); }, [dispatch]);

J'espère que cela t'aides!!

Oui, cette solution de contournement fonctionne, a déclaré
Pourquoi le sujet est clos ? Il y a aussi des mèmes à ce sujet... xd

Mon problème ressemble à celui-ci (exemple de code) :

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

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

Ainsi, comme dans le code, vous souhaitez modifier la userStatus lorsqu'il y a un changement dans userData et dans ce cas, si vous souhaitez vérifier la userStatus , vous devez l'ajouter à deps :

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

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

dans ce scénario, ce sera une boucle sans fin

@spmsupun
Vous pouvez utiliser le style de rappel de useState pour éviter d'introduire la variable userStatus dans le tableau de dépendances de useEffect.

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

Et c'est ce qu'on appelle les mises à jour fonctionnelles .

Solution --> il suffit d'ajouter l'envoi en dernier pour la dépendance
React Hook useEffect a une dépendance manquante : 'dispatch'.

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

@kennylbj C'est bien quand vous traitez avec un état, mon scénario réel est avec des accessoires. J'envoie un accessoire du parent et il change deux fois, donc usereffect appelle deux fois mais j'exécute un écouteur à l'intérieur et il écoutera deux fois.

@spmsupun Mais je pense qu'il est tout à fait normal de désinscrire l'écouteur précédent et d'enregistrer un nouvel écouteur chaque fois que les variables du tableau des dépendances ont changé (par exemple, lorsque l'ID utilisateur dans les accessoires a changé, l'écouteur devait également être modifié). Et ce comportement est ce que la réaction s'attend à avoir.

Si vous ne voulez toujours pas que l'auditeur soit appelé deux fois, je pense que vous devriez faire plus attention aux accessoires qui lui sont transmis et vous assurer qu'il ne sera pas modifié pendant les rendus.

@kennylbj eh bien je me
image
Je suppose que je dois gérer ça depuis la classe d'auditeur,

On dirait que votre écouteur est appelé deux fois même si les identifiants de socket sont les mêmes.

Je ne pense pas que cela se produira si la situation suivante se produit :

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

Y a-t-il d'autres variables dans le tableau des dépendances modifiées au cours de différents rendus et provoquent ce comportement ?

Ouais 3 dépendances, mais je trouve ça d'une manière différente

Pien

Comme suggéré dans le message d'avertissement, vous pouvez faire comme ça

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

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

wow,非常感谢你🙏

🚀 L'extrait de code ci-dessous fonctionne très bien pour moi

Le composant a monté

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

Sur changement de paramètre

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

Meilleure solution de contournement : reacti-hooks/exhaustive-deps : "off"
Je n'ai jamais trouvé cette fonction eslint utile. Déjà.

🚀 L'extrait de code ci-dessous fonctionne très bien pour moi

Le composant a monté

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

Sur changement de paramètre

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

bon travail.

Je ne pense pas que les documents de réaction couvrent tout à fait le cas d'utilisation de

Nous avons plusieurs façons d'appeler une fonction donnée, c'est-à-dire : setCenterPosition() . Il peut être appelé en surveillant le changement d'état (connecté via useEffect ), un gestionnaire de clics (appelé directement), etc.

Les documents de réaction suggèrent

C'est pourquoi vous voudrez généralement déclarer les fonctions nécessaires à un effet à l'intérieur de celui-ci.

Mais généralement dans des exemples du monde réel, nous devons réutiliser des fonctions comme nous le ferions normalement avec des méthodes d'instance sur un composant de classe ( this.setCenterPosition(...) ), et je commence à me demander si les crochets sont réellement bons pour les fonctionnalités complètes, composants complexes.

Je ne suis pas vraiment sûr, mais peut-être que la solution est useCallback

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

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

... mais c'est un peu dégoûtant pour moi, et j'espère qu'il y a un moyen plus propre. Peut-être que @gaearon peut confirmer ?

face au même problème, je peux désactiver le bu d'avertissement en utilisant cette ligne à la fin de useEffect // eslint-disable-next-line react-hooks/exhaustive-deps mais je ne veux pas l'utiliser

Voici mon code

`const [éléments, setItems] = useState([
{
nom: "test 1",
identifiant : 1
},
{
nom: "test 2",
identifiant : 2
},
{
nom: "test 3",
identifiant : 3
},
{
nom: "test 4",
identifiant : 4
},
{
nom: "test 5",
identifiant : 5
}
]);

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

Ma solution à ce problème a simplement été d'arrêter d'utiliser React Hooks pour ces cas. Si votre composant a besoin de beaucoup de logique d'état et d'événements de cycle de vie comme componentDidMount , utilisez simplement un composant de classe et évitez les maux de tête. Les composants de classe sont parfaitement corrects, et si ce fil prouve quelque chose, c'est que les crochets React ne sont pas prêts à les remplacer complètement lorsqu'une logique d'état complexe ou des événements de cycle de vie sont nécessaires (ils ne confèrent aucun avantage dans la plupart de ces cas - est-ce que votre code est _vraiment_ c'est bien mieux pour avoir utilisé React Hooks ?).

Je limiterai ma propre utilisation des crochets React à des crochets simples comme useState pour définir des drapeaux booléens et ce genre de choses. Si un composant devient suffisamment complexe pour avoir besoin de useEffect je considère cela comme un signe que peut-être un composant de classe convient mieux.

(Modifié pour plus de clarté).

Voici ma solution pour l'instant :

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

useEffect(mounted, []);

Merci @ra30r react /issues/15865#issuecomment-651254164

Cette page vous a été utile?
0 / 5 - 0 notes