reactjsuse-stateusecallback

Problem using useState inside useCallback hook


I'm having a problem where a useState hook "setSelectAll(!selectAll)" inside a useCallback function updates the value but the conditional below that sentence is using the old selectAll value, so i have to make two clicks to make it work, and I dont know why, any help wold be very aprreciated !

I have this useCallback hook that executes when I press a Button

<Button  onClick={onSelectAll}>{selectAll ? t`Deselect All` : t`Select All`}</Button>

And here's my callback,

const onSelectAll = useCallback(() => {
  setSelectAll(!selectAll);
  if(selectAll) {  
    let newItemsSelected = [...itemsSelected];
    arrayList.forEach(item => {
      newItemsSelected.push(item.id);
    })
    setItemsSelected(newItemsSelected);
    onSelectedChange(newItemsSelected);
  } else {
    setItemsSelected([]);
  }
}, [selectAll, itemsSelected]);```


Solution

  • You need to understand lifecycle of React component.

    useEffect will be fired after state change in re-render by updated state. And useCallback function is also changed.

    So you can call your callback function internally without direct call by changing your state.

    const onSelectAll = useCallback(() => {
      if(selectAll) {  
        let newItemsSelected = [...itemsSelected];
        arrayList.forEach(item => {
          newItemsSelected.push(item.id);
        })
        setItemsSelected(newItemsSelected);
        onSelectedChange(newItemsSelected);
      } else {
        setItemsSelected([]);
      }
    }, [selectAll, itemsSelected]);
    
    <Button  onClick={setSelectAll(prevSelectAllState => !prevSelectAllState);}>{selectAll ? t`Deselect All` : t`Select All`}</Button>