web-dev-qa-db-fra.com

Est-il sûr d'appeler des hooks React en fonction d'une condition constante?

Les Rules of Hooks nécessitent que les mêmes hooks et dans le même ordre soient appelés à chaque rendu. Et il y a une explication sur ce qui ne va pas si vous enfreignez cette règle. Par exemple ce code:

function App() {
  console.log('render');
  const [flag, setFlag] = useState(true);
  const [first] = useState('first');
  console.log('first is', first);
  if (flag) {
    const [second] = useState('second');
    console.log('second is', second);
  }
  const [third] = useState('third');
  console.log('third is', third);

  useEffect(() => setFlag(false), []);

  return null;
}

Sorties sur console

render 
first is first 
second is second 
third is third 
render 
first is first 
third is second 

Et provoque un avertissement ou une erreur.

Mais qu'en est-il des conditions qui ne changent pas pendant le cycle de vie de l'élément?

const DEBUG = true;

function TestConst() {
  if (DEBUG) {
    useEffect(() => console.log('rendered'));
  }

  return <span>test</span>;
}

Ce code n'enfreint pas vraiment les règles et semble bien fonctionner. Mais cela déclenche toujours l'avertissement eslint.

De plus, il semble possible d'écrire du code similaire basé sur des accessoires:

function TestState({id, debug}) {
  const [isDebug] = useState(debug);

  if (isDebug) {
    useEffect(() => console.log('rendered', id));
  }

  return <span>{id}</span>;
}

function App() {
  const [counter, setCounter] = useState(0);
  useEffect(() => setCounter(1), []);
  return (
    <div>
      <TestState id="1" debug={false}/>
      <TestState id="2" debug={true}/>
    </div>
  );
}

Ce code fonctionne comme prévu.

Est-il donc sûr d'appeler des hooks à l'intérieur d'une condition lorsque je suis sûr qu'elle ne changera pas? Est-il possible de modifier la règle eslint pour reconnaître de telles situations?

La question porte davantage sur l'exigence réelle et non sur la manière de mettre en œuvre un comportement similaire. Pour autant que je sache, il est important de

assurez-vous que les hooks sont appelés dans le même ordre à chaque rendu d'un composant. C’est ce qui permet à React de conserver correctement l’état des Hooks entre plusieurs appels useState et useEffect

Et il y a une place pour les exceptions à cette règle: "N'appelez pas de hooks à l'intérieur de boucles, de conditions ou de fonctions imbriquées".

10
UjinT34

Veuillez ne pas utiliser ce modèle. Cela peut fonctionner dans votre exemple mais ce n'est pas Nice (ou idiomatique).

Le modèle standard (pour une bonne raison) est que l'état initial est déclaré dans le constructeur, puis mis à jour en réponse à une condition du corps (setState). React Les crochets reflètent cette fonctionnalité dans les composants sans état - elle devrait donc fonctionner de la même manière.

Deuxièmement, je ne vois pas en quoi il est utile d'ajouter dynamiquement cet élément d'état et de provoquer des problèmes de rendu ultérieurement sur la ligne. Dans votre exemple, un simple const fonctionnerait tout aussi bien - il n'y a aucune raison d'utiliser l'état dynamique.

Considère ceci:

return (<React.Fragment>{second}</React.Fragment>)

Cela rompt avec une erreur de référence lorsque vous n'avez pas défini second.

0
jsdeveloper