TanStackT
TanStack7mo ago
7 replies
urgent-maroon

setQueryData & nested arrays immutability

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

- 1) if I update the mapping to always append some random UUID to the name, it's seems like useMemo is triggering
- 2) If I disable structuralSharing on query level the useMemo works
Was this page helpful?