web-dev-qa-db-fra.com

Comment utiliser le crochet d'usureFEffect correctement avec la dépendance du tableau. J'ai passé l'état de Redux Store et toujours, mon composant rend infiniment

J'utilise l'utilisation d'ussEffeCect et obtenez une liste des données d'utilisateurs avec l'appel de récupération à l'aide de la fonction gettstoreUsers qui envoie une action sur la réponse et les magasins acheteur (qui est un tableau) à l'intérieur du Redux boutique.

Dans la dépendance de la matrice, je vous écris [Shopusuers]. Je ne sais pas pourquoi cela cause-t-il un rendu infini.

Voici comment j'utilise UseEffect Crochet:

useEffect(() => {
    const { getStoreUsers, shopUsers } = props;
    setLoading(true);
    getStoreUsers().then(() => {
      setLoading(false);
    }).catch(() => {
      setLoading(false);
    });
  }, [shopUsers]);

Je souhaite reformuler uniquement des composants lorsque des données à l'intérieur des boutiques des boutiques changent.

Si j'écris des shopusutilisateurs. Longueur à l'intérieur de la dépendance de la matrice. Il s'arrête de re-rendu.

Mais supposons que j'ai une page qui s'ouvre lorsque l'utilisateur clique sur une liste d'utilisateurs et met à jour les données utilisateur à la page suivante. Après la mise à jour, je souhaite que l'utilisateur redevienne sur le même composant qui n'est pas démonté précédemment. Donc, dans ce cas, la longueur de la matrice reste la même, mais les données intérieures de l'indice Array sont mises à jour. Donc, les magasins. Longueur ne fonctionnera pas dans ce cas.

4
shubham choudhary

Vous pouvez faire un crochet personnalisé pour faire ce que vous voulez:

Dans cet exemple, nous remplacons le dernier élément de la matrice et nous voyons la sortie dans la console.

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import { isEqual } from "lodash";

const usePrevious = value => {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
};

const App = () => {
  const [arr, setArr] = useState([2, 4, 5]);
  const prevArr = usePrevious(arr);

  useEffect(() => {
    if (!isEqual(arr, prevArr)) {
      console.log(`array changed from ${prevArr} to ${arr}`);
    } 
  }, [prevArr]);

  const change = () => {
    const temp = [...arr];
    temp.pop();
    temp.Push(6);
    setArr(temp);
  };

  return (
      <button onClick={change}>change last array element</button>
  )
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Exemple en direct ici .

7
Colin Ricardo

Votre effet est déclenché sur la base des "shopusutilisateurs", qui déclenche elle-même une action Redux qui met à jour les "shopusutilisateurs" et c'est pourquoi il continue de tirer infini.

Je pense que ce que vous voulez optimiser est le rendu de votre composant lui-même, car vous utilisez déjà Redux, je suppose que vos accessoires/état sont immuables, vous pouvez donc utiliser React.memo Pour reformuler votre composant que lorsque l'une de ses accessoires change.

De plus, vous devez définir votre variable d'état/accessoires en dehors de vos crochets car ils sont utilisés dans la portée de la fonction entière comme.

Dans votre cas, si vous passez un tableau vide en tant que deuxième paramètre de mémo, il ne tirera que sur le composantDidmount, si vous passez null/non défini ou ne laissez rien, il sera tiré sur ComponentDidMount + ComponentDidUpdate, si vous souhaitez optimiser C'est que même lorsque les accessoires changent/composant met à jour le crochet ne tire pas à moins qu'une variable spécifique change alors vous pouvez ajouter une variable comme deuxième argument

React.memo(function(props){
  const [isLoading, setLoading] = useState(false);
  const { getStoreUsers, shopUsers } = props;
  useEffect(() => {
    setLoading(true);
    getStoreUsers().then(() => {
      setLoading(false);
    }).catch((err) => {
      setLoading(false);
    });
  }, []);
...
})
2
Khaled Osman