J'utilise des hooks de réaction dans un composant fonctionnel et je me demande à quoi sert useEffect lorsque vous ne spécifiez pas de dépendance. Je connais l'état de la documentation, il est utilisé pour les effets secondaires, mais ma question est pourquoi ces effets secondaires ne peuvent-ils pas simplement être exécutés avec du JS simple à l'intérieur du composant fonctionnel? Comme exemple très basique, je jouais avec le code suivant:

import {useEffect, useState} from 'react'

function Child () {

  const [clickCount, updateCount] = useState(0)

  console.log('Run outside of useEffect')

  useEffect(()=>{
    console.log("Run inside of useEffect")
  })


  return (

    <button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
  )
}

export default Child

Comme vous vous en doutez étant donné qu'il s'agit essentiellement d'une fonction JS normale, à chaque re-rendu causé par un clic de bouton, les deux console.log sont exécutés.

Je comprends pourquoi vous souhaiterez peut-être utiliser useEffect dans une situation telle que ci-dessous, où vous ne souhaitez exécuter useEffect que si quelque chose de spécifique change:

import {useEffect, useState} from 'react'

function Child () {

  const [clickCount, updateCount] = useState(0)

  console.log('Run outside of useEffect')

  //this now only runs when `someVariable` changes
  useEffect(()=>{
    
    console.log("Run inside of useEffect")
  }, [someVariable])


  return (

    <button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
  )
}

export default Child

Mais cela soulève la question, quel est l'intérêt d'utiliser useEffect à moins que vous ne spécifiiez la matrice de dépendances comme second argument? Les effets secondaires ne peuvent-ils pas être exécutés normalement en utilisant JS ordinaire?

3
Sean 25 oct. 2020 à 15:50

2 réponses

Meilleure réponse

quel est l'intérêt d'utiliser useEffect sauf si vous spécifiez la matrice de dépendances comme second argument?

La spécification du tableau de dépendances est une optimisation pour indiquer à React de ne pas exécuter l'effet si certaines valeurs n'ont pas changé entre les différents rendus d'un composant.

Les effets secondaires ne peuvent-ils pas être exécutés normalement en utilisant JS ordinaire?

Les effets qui sont exécutés au niveau supérieur à l'intérieur du composant fonctionnel s'exécutent d'une manière différente par rapport à l'effet à l'intérieur du hook useEffect.

Lorsque les effets sont à l'intérieur du useEffect:

  • Ils sont exécutés après que le navigateur a peint l'écran, c'est-à-dire après que React a appliqué les modifications au DOM.
  • Avant d'exécuter à nouveau l'effet, useEffect peut exécuter la fonction de nettoyage, si la fonction de nettoyage est fournie.
  • La spécification du tableau de dépendances vous permettra d'ignorer l'exécution de l'effet après chaque nouveau rendu du composant.

A cause des points mentionnés ci-dessus, vous voulez toujours que les effets secondaires soient exécutés à l'intérieur du hook useEffect.

En ce qui concerne les effets au niveau du code de niveau supérieur dans le composant fonctionnel, tenez compte des points suivants:

  • Exécutera l'effet avant que l'utilisateur ne voie quoi que ce soit à l'écran, c'est-à-dire que l'effet s'exécutera avant que React ne mette à jour le DOM.

  • Vous n'aurez aucun mécanisme de nettoyage qui pourrait être exécuté avant de réexécuter l'effet.

1
Yousaf 25 oct. 2020 à 13:37

À partir de la documentation:

les effets programmés avec useEffect n'empêchent pas le navigateur de mettre à jour l'écran. Cela rend votre application plus réactive. La majorité des effets ne doivent pas nécessairement se produire de manière synchrone.

Le code à l'intérieur du hook useEffect est exécuté après la mise à jour du DOM. Voilà la différence.

Exemple:

function App() {

  let [hi, setHi] = React.useState(false);
  let [inEffect, setInEffect] = React.useState(true);
  let msg = inEffect ? "useEffect (DOM will be updated immediately)" : "functional component (it will block DOM update)";
  
  return (
    <React.Fragment>
      <p>
        Long-running code is in {msg} {" "}
        <button onClick={() => (setInEffect(!inEffect), setHi(false))}>switch</button>
      </p>
      <button onClick={() => setHi(true)}>Say Hi</button>
      { hi ? <Hi {...{inEffect}}/> : null }
    </React.Fragment>
  );
}

function Hi({inEffect}) {
  !inEffect && block();
  React.useEffect(() => inEffect && block());
  return <h1>Hi!</h1>
}

function block(time = 2000) {
  const now = Date.now();
  while(now + time > Date.now());
}


ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
3
marzelin 25 oct. 2020 à 14:15