simplify PetAppearance client-side caching

Previously, we would load all `petAppearances` in `PosePicker`, and use cache keys to instantly find it again as a single `petAppearance` in `OutfitPreview` after switching poses.

In this change, we instead have `PosePicker` explicitly load all 6 poses as separate `petAppearance` queries. This simplifies cache sharing between the two components' queries: Apollo can do it automatically, because they were queried the same way in the first place.

I'm doing this in preparation for changing the `id` field of `PetAppearance`, to become `petStateId`. This will help me build pet appearance support tools, by giving the appearances stable identifiers that won't be affected by editing which pose an appearance is!
This commit is contained in:
Emi Matchu 2020-08-27 21:26:24 -07:00
parent 5f4952b123
commit bf21716db0
2 changed files with 79 additions and 31 deletions

View file

@ -376,36 +376,93 @@ function usePoses(speciesId, colorId, selectedPose) {
const { loading, error, data } = useQuery( const { loading, error, data } = useQuery(
gql` gql`
query PosePicker($speciesId: ID!, $colorId: ID!) { query PosePicker($speciesId: ID!, $colorId: ID!) {
petAppearances(speciesId: $speciesId, colorId: $colorId) { happyMasc: petAppearance(
speciesId: $speciesId
colorId: $colorId
pose: HAPPY_MASC
) {
...PetAppearanceForPosePicker
}
sadMasc: petAppearance(
speciesId: $speciesId
colorId: $colorId
pose: SAD_MASC
) {
...PetAppearanceForPosePicker
}
sickMasc: petAppearance(
speciesId: $speciesId
colorId: $colorId
pose: SICK_MASC
) {
...PetAppearanceForPosePicker
}
happyFem: petAppearance(
speciesId: $speciesId
colorId: $colorId
pose: HAPPY_FEM
) {
...PetAppearanceForPosePicker
}
sadFem: petAppearance(
speciesId: $speciesId
colorId: $colorId
pose: SAD_FEM
) {
...PetAppearanceForPosePicker
}
sickFem: petAppearance(
speciesId: $speciesId
colorId: $colorId
pose: SICK_FEM
) {
...PetAppearanceForPosePicker
}
}
fragment PetAppearanceForPosePicker on PetAppearance {
id id
petStateId petStateId
bodyId bodyId
pose pose
...PetAppearanceForOutfitPreview ...PetAppearanceForOutfitPreview
} }
}
${petAppearanceFragment} ${petAppearanceFragment}
`, `,
{ variables: { speciesId, colorId } } { variables: { speciesId, colorId } }
); );
const petAppearances = data?.petAppearances || [];
const buildPoseInfo = (pose) => {
const appearance = petAppearances.find((pa) => pa.pose === pose);
return {
...appearance,
isAvailable: Boolean(appearance),
isSelected: selectedPose === pose,
};
};
const poseInfos = { const poseInfos = {
happyMasc: buildPoseInfo("HAPPY_MASC"), happyMasc: {
sadMasc: buildPoseInfo("SAD_MASC"), ...data?.happyMasc,
sickMasc: buildPoseInfo("SICK_MASC"), isAvailable: Boolean(data?.happyMasc),
happyFem: buildPoseInfo("HAPPY_FEM"), isSelected: selectedPose === "HAPPY_MASC",
sadFem: buildPoseInfo("SAD_FEM"), },
sickFem: buildPoseInfo("SICK_FEM"), sadMasc: {
...data?.sadMasc,
isAvailable: Boolean(data?.sadMasc),
isSelected: selectedPose === "SAD_MASC",
},
sickMasc: {
...data?.sickMasc,
isAvailable: Boolean(data?.sickMasc),
isSelected: selectedPose === "SICK_MASC",
},
happyFem: {
...data?.happyFem,
isAvailable: Boolean(data?.happyFem),
isSelected: selectedPose === "HAPPY_FEM",
},
sadFem: {
...data?.sadFem,
isAvailable: Boolean(data?.sadFem),
isSelected: selectedPose === "SAD_FEM",
},
sickFem: {
...data?.sickFem,
isAvailable: Boolean(data?.sickFem),
isSelected: selectedPose === "SICK_FEM",
},
}; };
return { loading, error, poseInfos }; return { loading, error, poseInfos };

View file

@ -16,15 +16,6 @@ const typePolicies = {
toReference({ __typename: "Item", id }, true) toReference({ __typename: "Item", id }, true)
); );
}, },
// Teach Apollo how to serve `petAppearance` queries from the cache. That
// way, when you switch pet poses, Apollo knows it already has the
// appearance data and doesn't need to ask the server again!
petAppearance: (_, { args, toReference }) => {
const { speciesId, colorId, pose } = args;
const id = `${speciesId}-${colorId}-${pose}`;
return toReference({ __typename: "PetAppearance", id }, true);
},
}, },
}, },