How do I wait for state to update using Hooks. When I submit my form I need to check if termsValidation
is false before running some additional code. If the state has just changed it doesn't pick up on this.
import React, { useState } from 'react'; export default function Signup() { const [terms, setTerms] = useState(''); const [termsValidation, setTermsValidation] = useState(false); function handleSubmit(e) { e.preventDefault(); if (!terms) { setTermsValidation(true); } else { setTermsValidation(false); } if (!termsValidation) { console.log('run something here'); } } return ( <div> <form> <input type="checkbox" id="terms" name="terms" checked={terms} /> <button type="submit" onClick={handleSubmit}> Sign up </button> </form> </div> ); }
Use the useEffect hook to wait for state to update in React. You can add the state variables you want to track to the hook's dependencies array and the function you pass to useEffect will run every time the state variables change.
PureComponent , the state update using the updater provided by useState hook is also asynchronous, and will not be reflected immediately.
The reason why the state doesn't update immediately is because for each render, the state is immutable. …are both constants values ! So they're immutable. The state remains constant inside the render but can be changed between two renders.
To update the state, call the state updater function with the new state setState(newState) . Alternatively, if you need to update the state based on the previous state, supply a callback function setState(prevState => newState) .
The useState
hook is asynchronous but it doesn't have a callback api like setState
does. If you want to wait for a state update you need a useEffect
hook:
import React, { useState, useEffect } from 'react'; export default function Signup() { const [terms, setTerms] = useState(''); const [termsValidation, setTermsValidation] = useState(false); useEffect(() => { if (!termsValidation) { console.log('run something here'); } }, [termsValidation]); function handleSubmit(e) { e.preventDefault(); if (!terms) { setTermsValidation(true); } else { setTermsValidation(false); } } return ( <div> <form> <input type="checkbox" id="terms" name="terms" checked={terms} /> <button type="submit" onClick={handleSubmit}> Sign up </button> </form> </div> ); }
Changing state like setTermsValidation
is asynchronous action which means it's not immediate and the program does not wait for it. It fires and forgets. Hence, when you call setTermsValidation(true)
the program will continue run the next block instead of waiting termValidation to change to be true. That's why termsValidation will still have the old value.
You can just do this
function handleSubmit(e) { e.preventDefault(); if (!terms) { setTermsValidation(true); } else { setTermsValidation(false); // assuming you want to run something when termsvalidation turn to false console.log('run something here'); } }
Or ideally use hooks useEffect()
useEffect(() => { if (!termsValidation) { console.log('run something here'); } }, [termsValidation]);
However, be careful because useEffect also runs on initial render.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With