0

I'm trying to update a state where there is an object array, but it somehow doesn't change state at all! I'm following this docs https://react.dev/learn/updating-arrays-in-state and checked many similar questions with the very same solution, but it simply doesn't work for me. Here's the code:

    const [chips, setChips] = useState<Chip[]>([]);
    const [chipColor, setChipColor] = useState(null);
    const [chipValue, setChipValue] = useState("");

    function addChip(color: string) {
        if (chips.length >= 10) {
            alert("É permitido no máximo 10 fichas.")
            return;
        }

        const chip: Chip = {color: color, value: chipValue}
        setChips([...chips, chip])
        // setChips(prev => [...prev, chip]) doesn't work either
        console.log("WHYYYY")
        setData({...formData, chips})
        setChipValue(null)
        setChipColor(null)
    }

    function handleClose(e, id) {
        setChips(chips.filter(chip => chip.value !== id))
    }

    return (<VStack space="2.5" minW={"250"} justifyContent='center' alignContent='center'>
            <FormControl>
                <FormControl.Label _text={{bold: true}}>Valor</FormControl.Label>
                <Input
                    size={"lg"}
                    keyboardType='numeric'
                    value={chipValue}
                    onChangeText={text => {
                        setChipValue(text?.replace(/[^0-9]/g, ''))
                    }}
                    maxLength={4}
                />
            </FormControl>
            <FormControl>
                <FormControl.Label _text={{bold: true}}>Cor</FormControl.Label>
                <Select selectedValue={chipColor} minWidth="200" accessibilityLabel="Escolha a cor"
                        placeholder="Escolha a cor"
                        size={"lg"}
                        _selectedItem={{
                            bg: chipColor,
                            endIcon: <CheckIcon size="5"/>
                        }}
                        onValueChange={colorValue => {
                            addChip(colorValue)
                        }}>
                    {colors.map((color, i) => {
                        return <Select.Item key={i} label={color.name} value={color.value}/>
                    })}
                </Select>
            </FormControl>
            <Stack
                flexWrap={"wrap"}
                direction="row"
                justifyContent={"center"}
                space={3}>
                {chips.map((chip, i) => {
                    return (<CloseableCircle size="40px"
                                             bg={chip.color}
                                             shadow="9"
                                             handleClose={(e) => handleClose(e, chip.value)}
                                             key={i}>
                        <Text color={"white"} bold borderColor={"black"}>{chip.value}</Text>
                    </CloseableCircle>)
                })}
            </Stack>
            <StepsButtonGroup setPage={setPage} pages={pages} currentPage={currentPage}/>
        </VStack>
    );
}```
Gabriel Silva
  • 69
  • 1
  • 9
  • 2
    I don't know what `setData` does, but you're calling it with the old `chips` value. This might be the cause. Additionally, make sure you're always changing the values with the `prev` value: in the function itself, the value of chip is "frozen" to the value when `addChip` was created, i.e. `[]`, so accessing doesn't achieve what you hope for (google for `inlining` for more explanations on that matter). Same for the `setData` calls - use `prev`. – NotX Jun 19 '23 at 16:16
  • 1
    Does this answer your question? [Why does calling react setState method not mutate the state immediately?](https://stackoverflow.com/questions/30782948/why-does-calling-react-setstate-method-not-mutate-the-state-immediately) – Abe Jun 19 '23 at 20:37
  • @NotX Even using the arrow function with prevState didn´t work, either – Gabriel Silva Jun 28 '23 at 21:27

1 Answers1

0

Solved by removing setData from addChip and moving it to a kind of "Submit" button, with setData(prevState -> ({...prevState, chips: chips}). Somehow setData (setData: ({chips, ...otherProps}) => void) was changing chips values, then it was always setting the old value.

Thanks, guys! Using useEffect to handle async state change didn´t help, as Abe suggested question answers suggests.

Gabriel Silva
  • 69
  • 1
  • 9