rjcode
rjcode

Reputation: 1349

How to rerender component based on new data

I have below component which gets data expenses as props, Initial reader will show table with expenses values, but when row is deleted new data are stored in newExpenses which need to use in DataGrid

const DataTable = ({ expenses }) => {

  const handleDeleteCompleted = async () => {

    // Function for delete

    const newExpenses = await deleteExpense(fetchExpenseId)

    setOpenConfirmDelete(false);

    enqueueSnackbar(t('The user account has been removed'), {
      variant: 'success',
      anchorOrigin: {
        vertical: 'top',
        horizontal: 'right'
      },
      TransitionComponent: Zoom
    });
  };

  return (
    <>
         <div style={{ height: 800, width: "100%" }}>
            <DataGrid
              rows={expenses}
              columns={columns}
            />
         </div>

    </>
  );
};

export default DataTable;

Now I want to update DataGrid rows with newExpenses which are fetch with deleteExpense function.

How can Irerender DataGrid with new data?

Thank youm

Upvotes: 0

Views: 1140

Answers (2)

Francisco Aguirre
Francisco Aguirre

Reputation: 456

When you need to rerender a component based on data, you need to put that data into state. Whenever React state changes, the component gets rerendered.

In your case you'd need to put the prop expenses inside state.

import { useState } from 'react';

const DataTable = ({ expenses: initialExpenses }) => {
  const [expenses, setExpenses] = useState(initialExpenses);
  ...
  // On handler
  const newExpenses = await deleteExpense(fetchExpenseId);
  setExpenses(newExpenses);
}

That will make sure that your component gets rerendered.

This is the case in which the prop is the initial data, because you can't update the components props, you can only use them. In this example, your component is managing the state.

In the case where the parent component needs to manage the state, you'd need to not only pass expenses as a prop, but a callback to update it. Whenever a React prop changes, the component also rerenders. In this case you'd pass in both expenses and onDeleteExpense (for example). The parent component is the one who defines onDeleteExpense and handles the state (using useState).

const Parent = () => {
  const [expenses, setExpenses] = useState(someInitialValue);

  const onDeleteExpense = (expenseId) => {
    const newExpenses = await deleteExpense(expenseId);
    setExpenses(newExpenses);
  }

  return <DataTable expenses={expenses} onDeleteExpenses={onDeleteExpenses} />;
}

Upvotes: 1

David
David

Reputation: 218837

You're duplicating state and confusing where your system of record is. The first thing you need to do is decide:

Should the expenses state be managed in this component, or should it be managed in a parent and passed to this component?

Don't mix the two.

If the answer is that state should be managed in this component, remove the prop. Within this component you would fetch the data (perhaps once initially in a useEffect for example), store it in useState, and update that state accordingly (which will trigger a re-render).

If the answer is that state should be managed in a parent component, then that component needs to perform the updates/deletes/etc. It can pass functions to do that as additional props for this component to use. As that parent component updates its state, that would trigger a re-render of this child component.

Upvotes: 2

Related Questions