I am experiencing an issue with useMemo in my react app. Basically, it's NOT getting triggered when its dependency is updated.
Simplified code example:
return useMutation({
mutationFn: (id) =>
service.updateEntity(id),
onSuccess: (updatedEntity) => {
queryClient.setQueryData(
keys.entity(updatedEntity.id),
updatedEntity,
);
},
});
service.updateEntity calls and API and maps the result into a new object:
const mapToEntity = ({
id,
activities,
}: EntityAPI): Entity => {
return {
id: mapToIdentifier(id),
activities: activities.map(mapToActivity)
};
};
const mapToActivity = ({
name,
category,
timepoints,
}: ActivityAPI): Activity => {
return {
name,
category,
timepoints: timepoints.map(mapToTimepoint),
};
};
const mapToTimepoint = ({ name, active }: TimepointAPI): Timepoint => {
return {
name,
status: active
? timepointStatusSchema.enum.active
: timepointStatusSchema.enum.inactive,
};
};
As you can see entity contains a nested array: activities > timepoints. Even though I think I am mapping correctly, not mutating any existing state (I think), my useMemo which has a dependency on entity.activities is not getting triggered when I update the status of a nested timepoint. I can see the server returning the updated state.
useMemo(() => {
console.log('>>> entity.activities useMemo triggered');
}, [entity.activities]);
In the ui.dev course I remember react query having some smart caching mechanism: "structural sharing", could this be causing this issue?
Notes
-
- if I update the mapping to always append some random UUID to the name, it's seems like useMemo is triggering
-
- If I disable structuralSharing on query level the useMemo works