As far as I know, fragment masking is considered a best practice when developing graphql clients, but I'm having some difficulties wrapping my head around how to write even some simple react necessities with that level of obscurity. One common necessity is providing key
properties in iterations:
One example I'm working on is pulling repository data from Github to print cards with each of them. The query is:
fragment RepositoryCard on Repository {
resourcePath
description
}
Then, I'd use this query in a bigger one that request a user profile and gets some of their repositories:
query GetUserData($login: String!) {
user(login: $login) {
bio
name
repositories(first: 10) {
edges {
node {
...RepositoryCard
}
}
}
}
}
So far, so good. Then I'd map the responses to cards:
{
data?.user?.repositories?.edges?.map((repository) => (
<RepositoryCard
className="my-2"
repositoryNode={repository?.node}
/>
))
}
But then, I need a key
prop for this iteration. The best approach would be to use the resourcePath
since that's unique. However, since fragment masking is used, graphql-codegen
doesn't allow me to see the contents of the type of repository.node
, so I can't access resourcePath
from outside of the component to get it.
What's the common approach to solve this?
It seems like useFragment
is not a real hook, so it isn't necessary to follow the rules of hooks. In an answer to another question I see that the solution is to simply rename that function to something that won't trigger warnings (and better show the fact that it isn't a hook), so in your codegen.ts
:
generates: {
"./src/__generated__/": {
preset: "client",
plugins: [],
presetConfig: {
gqlTagName: "gql",
fragmentMasking: {
unmaskFunctionName: "getFragmentData",
}
}
}
Then you can just call getFragmentData
(previously useFragment
) inside the map
without getting any warnings:
data?.repositories?.edges?.filter((r) => !!(r?.node))
.map((r) => r?.node)
.map((repository) => {
const key = getFragmentData(REPOSITORY_CARD_FRAGMENT, repository)!.resourcePath;
return (
<RepositoryCard
key={key}
className="my-2"
query={repository!}
/>
);
})