Home > OS >  React: useState array not updating
React: useState array not updating

Time:12-10

When you push an array, data is pushed. However if you check in console.log, data is not imported. It seems to be a delay. Can you tell me why is this happening?

is there solution for this?

Expected console.log result showing input, however empty array shows and if you click checkbox again then input appears.


  const [checked, setChecked] = useState<number[]>([])

  const handleAddListToArray = (id: number) => {
    console.log(checked)
    if (setChecked.includes(id)) {
      setChecked(checked.filter((item) => item !== id))
    } else {
      setChecked([...checked, id])
    }
  }

--- checkbox compornent ---

  const [isChecked, setIsChecked] = useState(false)

  const handleChange = () => {
    setIsChecked(!isChecked)
    handleAddListToArray(id)
  }

 <Checkbox checked={isChecked} onClick={() => handleChange()} />


CodePudding user response:

when you push an array, data is pushed however if you check in console.log data is not inported. it seems to be a delay can you tell me why is this happening?

The state-setting functions are asynchronous. In other words, if you wrote:

const [foo, setFoo] = useState(0);
setFoo(1);
console.log(foo); // logs 0, NOT 1

you would see 0 logged, not 1 ... at least initially. However, there'd be a log entry below that would show 1.

This is because set* function don't change the value in the function, but they do cause the component to be re-rendered after, which means the function is run again, and now uses the correct value..

however empty array shows and if you click checkbox again then input appears.

It's because of this code:

setIsChecked(!isChecked)

Initially you set isChecked to an array:

setChecked(checked.filter((item) => item !== id))

But then you changed it to !isChecked ... a boolean. Once you change it to a boolean, you can't change it back to an array.

CodePudding user response:

You check the setState-function if it includes the input, on your fourth row of code:

if (setChecked.includes(id))

I believe you want to chech the checked-state instead, like so:

if (checked.includes(id))

Also, consider using the useState-callback when you mutate your state based on the previous one. So instead of:

setChecked(checked.filter((item) => item !== id))

try:

setChecked((prevState) => prevState.filter((item) => item !== id))

You can also use this when you setting your isChecked state. This ensure that you get your latest known state and avoids getting in some wierd states because React updates the state asynchronous.

CodePudding user response:

Some suggestions

if (setChecked.includes(id)) {

should be (setChecked is a function)

if (checked.includes(id)) {

For setChecked(checked.filter((item) => item !== id))

better usage will be

setChecked(prevCheckedValues => prevCheckedValues.filter((item) => item !== id));

This way you will always get the current checked values when you do a setChecked.

Another way to use this is via a useCallback and pass the dependency array as [checked]

If you want to print checked values each time its changed you can use a useEffect (docs) with correct dependency array.

Usage example

useEffect(()=>{
   console.log("Checked", checked);
}, [checked])
  • Related