1
votes

Pourquoi useState hook appelle-t-il deux fois le code de valeur d'initialisation?

Supposons que nous ayons le code suivant:

const [obj, setobj] = useState(generateInitialObj());

Pourquoi se produit-il que generateInitialObj () soit appelé deux fois? J'ai ajouté la journalisation à generateInitialObj () et je viens de le remarquer. Cela semble se produire au tout début du cycle de vie du composant. Je pense qu'une fois que react obtient une valeur à partir de là, ça va y rester pour de bon. Pas besoin de le réobtenir. Des idées?


1 commentaires

Vous avez probablement un composant parent dont l'état est mis à jour et ré-rendu. Par conséquent, re-rendre votre composant enfant.


3 Réponses :


4
votes

C'est une technicité JavaScript. Il n'y a rien que React puisse faire pour empêcher generateInitialObj d'être appelé sur chaque rendu. Pour en tenir compte, React prend en charge l'API suivante à la place:

const [obj, setobj] = useState(() => generateInitialObj());


0 commentaires

0
votes

Je pense que le re-rendu du composant est la raison derrière cela. pouvez-vous s'il vous plaît publier la hiérarchie des composants?

Essayez également ceci:

const [obj, setobj] = useState(() => generateInitialObj());

voici un exemple fonctionnel: https://stackblitz.com/edit/react-mysrjp

p >


0 commentaires

0
votes

Je viens de tester et de confirmer que si vous utilisez un appel de fonction getInitialState () , il sera appelé à chaque fois, car il s'agit bien d'un comportement JS normal.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
function getInitialState() {
  console.log('Executing getInitialState...');
  return({
    propA: 'foo',
    propB: 'bar'
  });
}

function App() {
  console.log('Rendering App...');
  const [myState,setMyState] = React.useState(()=>getInitialState());
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  function updateApp() {
    setMyBoolean((prevState) => !prevState);
  }
  
  function changeAppState() {
    setMyState({
      propA: 'foo2',
      propB: 'bar2'
    });
  }
  
  return(
    <React.Fragment>
      <div>myState.propA: {myState.propA}</div>
      <div>myState.propB: {myState.propB}</div>
      <button onClick={updateApp}>Update App</button>
      <button onClick={changeAppState}>Change App State</button>
    </React.Fragment>
  );
}


ReactDOM.render(<App/>, document.getElementById('root'));

Mais si vous utilisez une déclaration de fonction () => getInitialState () à la place, elle ne sera appelée qu'une seule fois.

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
function getInitialState() {
  console.log('Executing getInitialState...');
  return({
    propA: 'foo',
    propB: 'bar'
  });
}

function App() {
  console.log('Rendering App...');
  const [myState,setMyState] = React.useState(getInitialState());
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  function updateApp() {
    setMyBoolean((prevState) => !prevState);
  }
  
  function changeAppState() {
    setMyState({
      propA: 'foo2',
      propB: 'bar2'
    });
  }
  
  return(
    <React.Fragment>
      <div>myState.propA: {myState.propA}</div>
      <div>myState.propB: {myState.propB}</div>
      <button onClick={updateApp}>Update App</button>
      <button onClick={changeAppState}>Change App State</button>
    </React.Fragment>
  );
}


ReactDOM.render(<App/>, document.getElementById('root'));

À part cela, les deux fonctionnent exactement de la même manière.


0 commentaires