0

I am using a Material-UI table to render data retrieved from an API>. There is a form to add new entries but when this adds to the data the table is not updating/re-rendering and I can't figure out why.

This is edited for brevity/clarity...

    const [data, setData] = useState();

    useEffect(() => {
        const fetchSummary = async () => {
            setLoading(true);
            const response = await axios
                .get<TSalesSummary[]>(`/sales/${$reporterId}`, {})
                .then((result) => {
                    setData(result.data);
                })
                .catch((error) => {
                    console.error('Retrieve Request Failed');
                    setError(error);
                })
                .finally(() => {
                    setLoading(false);
                })
        }

        if (!data) {
            fetchSummary();
        }

    }, [reporterId]);
    const onSubmit = async (values: any, actions: any) => {

        const result = await axios
            .post<TSalesSummary>(`/sales/` + props.identifier + '/invite', {
                first_name: values.firstName,
                last_name: values.lastName,
                email: values.email
            })
            .then((result ) => {
               data?.unshift(result.data);
               setData(data);
               setPage(0);
            })
            .catch((error) => {

            });
    }

Component:

            <TableContainer component={Paper}>
                <Table sx={{minWidth: 650}} aria-label="simple table">
                    <TableHead>
                        <TableRow>
                            <TableCell sx={{fontWeight: 700}}>
                                First Name
                            </TableCell>
                            <TableCell align="left" sx={{fontWeight: 700}}>
                                Last Name
                            </TableCell>
                            <TableCell align="left" sx={{fontWeight: 700}}>
                                Email
                            </TableCell>
                            <TableCell align="left" sx={{fontWeight: 700}}>
                                Status
                            </TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {(data
                            ? data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                            : data
                        ).map((row) => (
                        <TableRow
                            key={row.identifier}
                            sx={{
                                '&:last-child td, &:last-child th': {border: 0},
                            }}
                        >
                            <TableCell component="th" scope="row">{ row.first_name }</TableCell>
                            <TableCell align="left">{ row.last_name }</TableCell>
                            <TableCell align="left">{ row.email }</TableCell>
 
                        </TableRow>
                        ))}
                        {data.length === 0 &&
                            <TableRow>
                                <TableCell rowSpan={3}>No records found</TableCell>
                            </TableRow>
                        }
                    </TableBody>
                    <TableFooter>
                        <TableRow>
                            <TablePagination
                                rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
                                colSpan={3}
                                count={data.length}
                                rowsPerPage={rowsPerPage}
                                page={page}
                                SelectProps={{
                                    inputProps: {
                                        'aria-label': 'rows per page',
                                    },
                                    native: true,
                                }}
                                onPageChange={handleChangePage}
                                onRowsPerPageChange={handleChangeRowsPerPage}
                            />
                        </TableRow>
                    </TableFooter>
                </Table>
            </TableContainer>

When onSubmit runs the data is updated (I can see in the console) but the table does not re-render. What do I need to do to make the table also update?

3
  • Your useEffect dependency should be on data to rerender the screen Feb 17 at 10:28
  • Thanks but wouldn't that recall the fetch which I don't want?
    – Rob Irvin
    Feb 17 at 10:32
  • then you can fetch just at the first render of the screen with empty array dependency and then use an empty useeffect with data dependency Feb 17 at 12:37

1 Answer 1

2

Inside the onSubmit handler, you are mutating the state variable data and try to update the mutated data.

data?.unshift(result.data);
setData(data);

It won't work because to react, the array object doesn't change (the reference to the array stay the same). The correct way to update a state variable is by setting it to a new data array.

const newData = [...result.data, ...data];
setData(newData);

According to the React docs,

Never mutate state directly, as calling setState() afterwards may replace the mutation you made. Treat state as if it were immutable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.