Reputation: 540
I'm new to react and this could be a fairly simple question to answer. I'm using easy-peasy for state management and I have an action that updates global state, but the component is not re-rendered even after global state is updated. Here is the codesandbox link. In this example, when the save button is clicked, I'm changing the record to "lock" status which should make it editable. https://codesandbox.io/s/reactjs-playground-forked-sbbh6?file=/src/App.js
Upvotes: 3
Views: 1066
Reputation: 5692
As you are passing the store state to item again after clicking save, you need to listen for props change in Item
and set the state again to trigger rerender.
Therefore, the 1st step is to find out which value we want to monitor for changes. From the code, it is obvious that status
is the best candidate.
Item.js
// not the final solution
// monitor props status change, set the state again and trigger rerender
useEffect(() => {
setState({ ...state, ...props });
}, [props.status]);
However, there is a problem to tackle if we use props.status
to trigger rerender.
e.g.
When you first click the save on item 2, item status
change from open
-> lock
, the Item
rerender. No problem!.
But when you change the dropdown box from lock
to open
of item 2 and click the save
again, Item
will not rerender.
As the updated store status of item 2 is still marked as lock, previous status is also lock, there is no changes at all in react point of view.
You can check this codesandbox to simulate the issue.
To address this issue, we need to introduce extra property to monitor its change for rerender. I used updatedAt
to generate time on each update to let's react know there is a differences on the value and trigger rerender for us.
modal.js
items: [
{ id: 1212, title: "Watch mojos", subtitle: "", status: "open", updatedAt: null },
{ id: 1213, title: "Drink cheetos", subtitle: "", status: "open", updatedAt: null },
{ id: 1214, title: "Eat frodos", subtitle: "", status: "lock", updatedAt: null }
]
saveItem: action((state, payload) => {
console.log(payload);
state.items = state.items.map((d) => {
if (d.id === payload.id) {
d.status = "lock";
d.updatedAt = new Date(); // assign new date on each update
}
return d;
});
})
Item.js
useEffect(() => {
setState({ ...state, ...props });
}, [props.updatedAt]); // monitor update date change instead of status change
Here is the workable codesandbox
Upvotes: 2