reactjsreact-hooksmaterial-uiformikformik-material-ui

State change doesn't trigger rerender


I've set a MUI Table with its last row containing a few TextFields as such (content stripped for readability) :

[Generated rows...]
<TableRow>
  <TableCell component="th" scope="row">
    <TextField/>
  </TableCell> ...

  <TableCell>
    <Button variant="outlined" onClick={() => addFond()}>
        <Add />
    </Button>
  </TableCell>
</TableRow>

Above rows are to be generated from an Array coming from a persistent storage state. One row is to be added using the addFond() button and function:

const addFond = () => {
  userDefaults.assuranceVie ??= {}
  userDefaults.assuranceVie.tableFondsVI ??= []
  userDefaults.assuranceVie.tableFondsVI.push({ ...formik.values, id: uuidv4() })
  setDefaults(userDefaults)
}

I'm using a Formik form for the new row, and would like to create a new formik row for all the iterated rows above the last one.

When clicking the addFond() button, I expected the state to change and to rerender the whole component. I have a console.log printing the state at top-level of the component, but nothing prints when clicking.

Note that this Table component is embedded into an higher order tag.

After resolution edit :

I couldn't modify the state object and expect the change detection to work after using the setter since the state didn't actually change.


Solution

  • State change doesn't trigger rerender

    There's no any state change, actually. The re-render is not triggered because the previous value of state is exactly the same as the new one, since you are mutating it.

    userDefaults.assuranceVie ??= {} -> state mutation.

    You should base on the callback function of setState to be sure you refer to the current state and you should return a new object to avoid mutation.

    const addFond = () => {
      setDefaults((prev) => ({
         ...prev,
         assuranceVie: {
            ...(prev.assuranceVie || {}), // in case if not exists
            tableFondsVI: [
               ...(prev.assuranceVie?.tableFondsVI || []), 
               { ...formikValues, id: uuidv4() }
            ],
         }
      });
    }