I have a simple react component, the purpose is to create a list in which each item will be toggle in or out on click.
export type Choice= {
id: string
value: string
}
function Component({choices}){
const [selectedChoices, setSelectedChoices] = useState<Choice[]>([])
const handleSelectChoice = useCallback((choice: Choice) => {
setSelectedChoices((p) => {
const idx = p.findIndex((c) => c.id === choice.id)
if (idx > -1) {
p.splice(idx, 1)
console.log(p)
return [...p]
} else {
console.log(p, "SD")
return p.concat(choice)
}
})
}, [])
return (
<div>
{choices.map((choice) => (
<button
key={choice.id}
type="button"
className={` ${
selectedChoices.find((c) => c.id === choice.id) ? "selected" : ""
}`}
onClick={() => handleSelectChoice(choice)}
>
{choice.value}
</button>
))}
</div>
)
}
After some debugging (using refs and console logs), I found out that react development mode is triggering the set function twice.
Whenever the user clicks the button in strict mode, the state won't change at all because the
setSelectedChoices
gets called twice, basically canceling the user's action.
I understand the importance of strict mode and could not make it work yet. I can try and make it work using refs but wanted to know if there is any other way. How can I run such useState setters in strict mode and avoid side-effects? Any help is appreciated.