Let me put the Stack Overflow post that solved my problem here first.
I was doing essentially the same thing, but with activity editing. This is a function that I provided in the TripContext
:
1 | /** src/spa/contexts/TripContext.js **/ |
Note that I was trying to update activity by passing an array to setActivities
.
This is how I used it in ActivityCard
:
- Component:
1
2
3
4
5
6
7
8
9
10
11
12/** src/spa/components/cards/ActivityCard.js, part of return statement **/
<DateTimePicker
value={activity.start}
ampm={false}
onChange={start =>
handleEdit({ start }, updateOneActivity)
}
open={startChanging}
onClose={() => setStartChanging(false)}
TextFieldComponent={() => null}
showTodayButton
/> - Handler:
1
2
3
4
5
6
7
8/** src/spa/components/cards/ActivityCard.js **/
const handleEdit = (activityPatch, updateOneActivity) => {
if (checkTimeValid(activityPatch)) {
updateOneActivity(activityPatch, activityID);
} else {
setTimeErrorDisplay(true);
}
};
When I edit the activity, the database is updated but I dont get a page update.
If I log the activities
in the console after the setActivity
is called, I can see that the activities
array remain the old value.
It is to be kept in mind that the setter defined with useState
has the same behaviour as setState
in class components. Have a look at the setState documentation.
setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state.
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.
So my solution would be to pass setActivity
with an updater function(state, props) => stateChange
.
Here’s my updated code in the TripContext
:
1 | /** src/spa/contexts/TripContext.js **/ |
Works smooth like silk. Now when I update activities in ActivityCard
or anywhere else, the Timeline of the trip will be updated.