Reputation: 1349
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
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
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