-2

I dont know if it is right or not but I did this with my useState to having multiple states but now I'm getting undefined instead of switching between true and false. How can I fix this

let [Click,setClick] = useState({button1:false,button2:false})

const changeItem = () =>{
setClick(!Click.button1)
console.log(Click.button1)
}

This function applied on a Button component's onclick event First I'm getting false then undefined

Joji
  • 3
  • 1

3 Answers3

2

What is happening

The initial state is:

{button1:false,button2:false}

Then (via changeItem) you call setClick(!Click.button1) which sets a new state (false because !any_object is false).

Then you call console.log(Click.button1) which logs false because the initial state's button1 property is false.

Then a re-render is triggered which creates a new Click variable containing the new state and a new changeItem function which closes over the new Click variable.

Next time you call changeItem again and:

setClick(!Click.button1)

Click is false so Click.button1 is undefined so you set the state to true.

Then console.log(Click.button1) logs the previously closed over Click's (false) button1 property which is undefined because booleans don't have those properties.

How to update a property of an object in the state

You need to assign a new object to the state in which you only change the value you care about:

setState({
    ...Click, // Shallow copy all the old values
    button1: !Click.button1, // Change the one you care about
})

How to observe the change

Use a useEffect hook to log the value when the state changes:

useEffect( () => { console.log(Click); }, [Click] )

A note about style

By convention, variable names starting with capital letters are reserved for constructor functions and classes. Don't use them to store data. Call it click.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

State updates in React do not reflect immediately.

You can read more about it here: useState set method not reflecting change immediately

Also, with useState hook, updates aren't merged and hence you have to update the complete object

You can use the callback approach to update the state like below

let [Click,setClick] = useState({button1:false,button2:false})

const changeItem = () =>{
   setClick(prev=> ({...prev, button1: !prev.button1}))
}  

// you can see the updated state here in the next render cycle
console.log(Click.button1);
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
0

The problem here is that in changeItem you're calling setClick(!Click.button1) which is resetting your entire Click state variable.

If you you're trying to change the state to be {button1: true, button2: false}, then you can use the spread operator to copy your state and then modify only the value of button1

const changeItem = () => {
  setClick({ ...Click, button1: !Click.button1 });
}

This should do it.

Vincent M
  • 156
  • 8