4

I am trying to call a handler from a parent function with the updated state value as an argument, however, the state does not update immediately after the setSelected is called as both console logs are printing false(the initial value). After the onClick function is completed however, it gets updated.

onClick={() => {
        console.log("Clicked: ", props.rank, props.suit, selected); 
        setSelected(!selected)
        console.log("selected: ", selected)
        // props.handle_card_selected(props.id, selected)
      }}
useEffect(() => {
    const check_border = () => {
      if (selected) {
        return "green"
      }
      return "black"
    }
    check_border()
  }, [selected])
Natnael Mekonnen
  • 125
  • 1
  • 1
  • 4
  • 1
    Please, [see this](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately). – devserkan Jul 14 '20 at 17:19

2 Answers2

13

Two things you need to know about the state update in React:

  • State is updated asynchronously
  • In any particular render, state and props don't change; changes are only reflected after component re-renders

If you want to log the updated value of selected, put the log statement in the useEffect hook.

You can't update and log the updated value of any state variable in the same render; component will have to re-render to reflect changes due to state update.

Similarly, if you want to call a function with the updated value of selected, call the function from inside the useEffect hook.

Yousaf
  • 27,861
  • 6
  • 44
  • 69
5

setState is an async function which is why it doesn't update the state immediately. There is another way, i.e. pass function in setSelected, through which you can achieve the required behaviour:

onClick={() => {
     console.log("Clicked: ", props.rank, props.suit, selected); 
     setSelected(prevSelected => {
       // props.handle_card_selected(props.id, !prevSelected)
       return !prevSelected
     })
}}

useEffect(() => {
  props.handle_card_selected(selected)
}, [selected, props.handle_card_selected])
Muhammad Ali
  • 2,538
  • 2
  • 16
  • 21
  • 1
    Functional update is better for what the OP is trying but if he wants to call a function he can do that using `useEffect`. – Ramesh Reddy Jul 14 '20 at 17:32
  • The state update function shouldn't have side-effects. It's a bad practice. Use something like `useEffect` if necessary. – Emile Bergeron Jul 14 '20 at 17:34