Voir l'extrait de getInitialState
ci-dessous indiquant que getInitialState
est exécuté sur chaque rendu. Même si la valeur renvoyée par celui-ci n'est utilisée que lors du 1er rendu.
Je sais que c'est un comportement Javascript normal. Mais y a-t-il un moyen de l'éviter en utilisant React?
<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 App() { function getInitialState() { console.log('Executing getInitialState...'); return({ foo: 'bar' }); } const [myState,setMyState] = React.useState(getInitialState()); const [myBoolean,setMyBoolean] = React.useState(false); return( <React.Fragment> <div>I am App</div> <div>My state: {JSON.stringify(myState)}</div> <div>My boolean: {JSON.stringify(myBoolean)}</div> <button onClick={()=>setMyBoolean((prevState) => !prevState)}>Force Update</button> </React.Fragment> ); } ReactDOM.render(<App/>, document.getElementById('root'));
4 Réponses :
Essayez la React.useMemo
avec React.useMemo
<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 { foo: 'bar' }; } function App() { const getInitial = React.useMemo(() => getInitialState(), []); const [myState, setMyState] = React.useState(getInitial); const [myBoolean, setMyBoolean] = React.useState(false); return ( <React.Fragment> <div> I am App </div> <div> My state: {JSON.stringify(myState)} </div> <div> My boolean: {JSON.stringify(myBoolean)} </div> <button onClick={() => setMyBoolean(prevState => !prevState)}> Force Update </button> </React.Fragment> ); } ReactDOM.render(<App />, document.getElementById('root'));
useState
pas la fonction directement dans useState
, passez une fonction anonyme pour déclencher la fonction. Reportez-vous au Doc .
<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({ foo: 'bar' }); } function App() { const [myState,setMyState] = React.useState(()=>getInitialState()); const [myBoolean,setMyBoolean] = React.useState(false); return( <React.Fragment> <div>I am App</div> <div>My state: {JSON.stringify(myState)}</div> <div>My boolean: {JSON.stringify(myBoolean)}</div> <button onClick={()=>setMyBoolean((prevState) => !prevState)}>Force Update</button> </React.Fragment> ); } ReactDOM.render(<App/>, document.getElementById('root'));
C'est une bonne réponse, mais vous devez expliquer pourquoi et comment cela se produit.
getInitialState()
exécutera la fonction à chaque fois mais () => getInitialState()
passera la référence de la fonction afin qu'elle soit appelée une fois.
React gérera le useState
différemment selon les arguments. Dans votre code, getInitialState()
renverra une valeur. Et useState
traitera une référence de fonction différemment. S'il s'agit d'une fonction, elle ne sera exécutée que sur le rendu initial
Vous devez calculer votre état dans une fonction selon la documentation :
const [myState, setMyState] = useState(getInitialState);
Ou plus court:
const [myState,setMyState] = useState(() => { const initialState = getInitialState(); return initialState; });
Encore un autre crochet gotcha!
Toutes les bonnes solutions, mes deux cents = la solution la plus courte de Dominic ci-dessus. :)
Vous passez une fonction calculée (le résultat de la fonction est passé à useState) Si vous passez votre fonction, React sait qu'il n'a besoin d'appeler cette fonction que la première 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 App() { function getInitialState() { console.log('Executing getInitialState...'); return({ foo: 'bar' }); } const [myState,setMyState] = React.useState(getInitialState); // <-- pass the function, not the call to the function (result) const [myBoolean,setMyBoolean] = React.useState(false); return( <React.Fragment> <div>I am App</div> <div>My state: {JSON.stringify(myState)}</div> <div>My boolean: {JSON.stringify(myBoolean)}</div> <button onClick={()=>setMyBoolean((prevState) => !prevState)}>Force Update</button> </React.Fragment> ); } ReactDOM.render(<App/>, document.getElementById('root'));
pourquoi en avez-vous besoin pour être une fonction plutôt qu'une constante?