web-dev-qa-db-fra.com

Le crochet useEffect ne se déclenche pas après un changement d'état

J'ai deux composants frères qui partagent l'état via le contexte en réaction. L'état partagé entre les composants est un tableau.

Si je mets à jour l'état arr dans un composant, je veux que l'autre composant écoute cette mise à jour et fasse quelque chose en conséquence. Lorsque j'utilise useEffect dans le deuxième composant, j'écoute les changements dans la variable d'état arr.

Par exemple:

// App Component -------
const App = props => {
 const { arr, setArr } = useContext(GlobalContext)

 const handleChange = () => {
   const newArr = arr
   [10, 20, 30, 40].map(v => {
     newArr.Push(v)
     setArr(newArr)
   })

  return (...)
}

// App2 (Sibling) Component 
const App2 = props => {
  const { arr, setArr } = useContext(GlobalContext)
  const [localArr, setLocalArr] = useState(0)

  useEffect(
    () => {
      updateLocalState()
    },
    // fire if "arr" gets updated
    [arr]
  )

  const updateLocalState = () => {
    setLocalArr(localArr + 1)
  }

  return (...)
}

Le crochet useEffect est seulement déclenché sur le rendu initial, bien que l'état de arr soit mis à jour.

Je sais que déclarer une nouvelle variable const newArr = arr À ma variable d'état est une référence, donc newArr.Push(v) est techniquement une mutation d'état. Cependant, l'état est toujours mis à jour, aucun avertissement n'est lancé et useEffect ne fait rien.

Pourquoi useEffect n'est-il pas appelé alors que l'état est mis à jour? Est-ce à cause de la mutation d'état?

Deuxième question: pourquoi n'y a-t-il aucun avertissement ou erreur concernant une mutation d'état? Les mutations d'état sont dangereuses - Si cela se produit, je m'attendrais à une sorte d'avertissement.

Démo en direct ici:

Edit 7wzlo8y4m1

8
lsimonetti

Le tableau que vous passez comme deuxième argument à useEffect vérifie uniquement si les éléments du tableau sont === aux éléments qu'il contenait dans le rendu précédent. const newArr = arr; mènera à newArr === arr car il ne crée pas de nouveau tableau, ce qui n'est pas ce que vous voulez.

Créez un nouveau tableau avec tous les éléments dans arr et cela fonctionnera comme prévu.

const App = props => {
 const { arr, setArr } = useContext(GlobalContext)

 const handleChange = () => {
   const newArr = [...arr]
   [10, 20, 30, 40].forEach(v => {
     newArr.Push(v)
   })
   setArr(newArr)
 }

  return <>{/* ... */}</>
}
13
Tholle