It’s not that you have to click two, it’s that you’re rendering the tick after it happens. So you update once, but you’re not updating the state. The next time you click that actually updates the state to take into account the previous change, then you click again and it takes into account the previous change and so on.
The components are all functions, to get them to return an version of the rendering code relating to that updated list you need to run the relevant functions again, which isn’t happening here immediately.
There are several reasons why this might happen, all related to the fact you’re not properly updating the state and causing a rerender on click, but without any code it’s not very easy to provide help.
So those setStates do cause a rerender, but you’re explicitly setting the string of text to whatever the value was before the rerender. Just do the logic you want to create a new array of the checkboxes state + the derived display value, then pass those values to the setState calls.
What I said before applies absolutely here: those values in setState aren’t really that special, and the components are functions. When you setState it’s just taking the new values and passing them into the function again to rerun it. There’s no point between the setCheckBox and the next line in that handler function where the value of checkBox has changed, the whole function needs to run again before that happens. At which point checkBox is a new value, but then langValue is on the last value. And so on.
Fix is extremely simple, so for example (sorry, some of the names may be different as I wasn’t looking at the original code – tbh should try to use more descriptive names for clarity anyway but ):
Edit: it’s not a great idea to use nested structures as state. The issue is that you always have to be careful to ensure you make a new version every time; it makes it really easy to accidentally mutate instead of clone. And React does a check to see if it needs to update a value, so if there’s a mutation, the object reference hasn’t changed, so no update. Can’t really avoid this completely here, so I’d maybe do something like this:
Because useEffect will always be triggered after the state was set, and before the function returns (I think, but not a React expert by any means.)
The only change I did was to put the setLangValue in the useEffect hook
EDIT
The problem with the original code seems to be that the setLangValue does not wait the setCheckBox to finish, and then is always accessing an old value (the previous state of the array.)
It seems that react expects each state to be independent of each other. That is why useEffect is sort of useful (because it waits the first setCheckBox to be done.)