Home > Software engineering >  setState in useEffect not update
setState in useEffect not update

Time:02-26

Got an input and want to pass value to handler:

const [term, setTerm] = useState('');

<Input type="text" onBlur={(e)=>handleFilter(e, 'params')} />

const handleFilter = async(e, params) => {
//... api call and etc
setTerm(e.target.value); // update term
console.log(term) // return none-updated value! but I need fresh value
// send this value to another api
}

I want to make an search filter function, for ex. if I enter a, console return empty, then I enter b console return a ! it means term not update immediately, then I used useEffect but inside the useEffect I got new value, but inside handleFilter function still console return prev value.

useEffect(() => {
    getApi()
        .then(data => {
            console.log(data)
        })

    console.log(term) // works fine, return new value
    setTerm(term) // update term

}, [term])

I tried this but no success:

setTerm({...term, e.target.value});

Any solution? I'm new to react hook.

CodePudding user response:

I could be wrong on this one, but could this have something to do with you calling an async function from a normal event. This might cause some type of delay.

There is also the fast that useEffect is treated differently in React than a normal function, since it's integrated into React.

It could also be related to the [term] trigger in the useEffect but the event in your handleFilter isn't treated the same

CodePudding user response:

You can check this answer here.

This is because react's state update is async. You can't rely on its update right after calling setState. Put your effects (code that is run after a state is updated) in a useEffect hook.

const handleFilter = async(e, params) => {
  //... api call and etc
  setTerm(e.target.value); // update term
}

React.useEffect(() => {
  console.log(term) // return none-updated value! but I need fresh value
  // send this value to another api
}, [term]);

CodePudding user response:

setTerm is async and will update the term on the next render cycle. it is not updated immediately for the current render cycle. you can store the current value in a ref if you are curious what is happening behind the scenes

const termRef = React.useRef(term);
termRef.current = term;
const yourHandler = () => {
  setTimeout(() => console.log(termRef.current), 0);
}

CodePudding user response:

If we are going ahead with useEffect with an API call, please ensure to include async await scenario to ensure that setState updates after the data is fetched.

useEffect(async () => {
    const data = await getApi()
      

    console.log(term) // works fine, return new value
    setTerm(term) // update term

}, [term])

  • Related