Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for state to update when using hooks

Tags:

reactjs

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>   ); } 
like image 985
bp123 Avatar asked Mar 15 '19 02:03

bp123


People also ask

How wait for state changes in React hooks?

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.

Does useState hook update immediately?

PureComponent , the state update using the updater provided by useState hook is also asynchronous, and will not be reflected immediately.

Why setState hook is not updating 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.

How do I update my state hook?

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) .


2 Answers

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>   ); } 
like image 181
DoHn Avatar answered Sep 21 '22 18:09

DoHn


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.

like image 35
Gianfranco Fertino Avatar answered Sep 24 '22 18:09

Gianfranco Fertino