It would be very convenient if I could reference a fragment by value inline. An example:
const myFragment = gql`
fragment MyFragment on Widget {
name
gizmo { id }
}
`;
const myQuery = gql`
query MyQuery {
id
widgets {
...${myFragment}
}
}
`
Which of course would result in this query:
query MyQuery {
id
widgets {
...MyFragment
}
}
fragment MyFragment on Widget {
name
gizmo { id }
}
Compare to the current standard:
const myQuery = gql`
query MyQuery {
widgets {
id
...MyFragment
}
}
${myFragment}
Note that I have to include the fragment in two different places by two different names. Combined with the fact that fragments are usually in different files, this adds quite a bit of unnecessary friction and uncertainty to referencing a fragment.
I wrote a small helper function to do this. It converts the fragment from a named fragment to an inline one, which means that it will send some more data if you reuse the fragment inside your query. However, the dev experience is better.
function inlineFragment(parsedDoc) {
return parsedDoc.loc.source.body.replace(/fragment [_A-Za-z][_0-9A-Za-z]*/, '...');
}
It appears when merging parsed strings in another query, it only looks at loc.source.body.
Usage:
const productProps = inlineFragment(gql`
fragment ThisNameWillBeDiscarded on Product {
title
price
}
`);
const query = gql`
query GetProductData {
product(id: 1) {
${productProps}
}
}
`;
The reason of just wrapping the gql parsed string instead of writing a new helper that could do this in a more neat way, is that we keep all benefits that the tooling provides (including auto complete if you've configured it). :)
@alfredringstad Expanded on your great idea and make something akin to Relay's FragmentContainer. I've turned it into an HoC that supports both fragment maps and extrapolation of prop names from AST:
https://gist.github.com/simenbrekken/75368a1ee24deb161b8b7b088ca0f714
@alfredringstad thanks for the solution, it's very helpful and I'll probably use it for now. However I second this request. It would be nice to have a solution directly from graphql-tag so there is not that possibility of being broken by future updates.
I too would like to have what is requested here. I guess the implementation would be something like this:
Check if the interpolated variable is prefixed by ... and if the variable is a valid fragment document then just replace by the fragment name, and add the actual fragment to the end of the document.
Although I have not looked into the source yet so not sure if this is possible :-).
Thanks @jonaskello for your tip!
I prepared a PR to add support for inline/shorthand fragments: https://github.com/apollographql/graphql-tag/pull/224 馃槉
I am personally against this because without the explicit fragment names it's significantly harder to do code generation and validation. I'd be worried that beginners would use this syntax and then once they are ready to set up the tooling around it, be disappointed that it doesn't work. We intentionally chose to not allow this syntax during the early development of the library.
I agree that it's a bummer to have to list the fragment twice, but it's unfortunately the only solution that maintains compatibility with the widest range of tools. It might be worthwhile to have a version of graphql-tag that enables more concise syntax with some tradeoffs, but IMO that shouldn't live in this repo.
Most helpful comment
I wrote a small helper function to do this. It converts the fragment from a named fragment to an inline one, which means that it will send some more data if you reuse the fragment inside your query. However, the dev experience is better.
It appears when merging parsed strings in another query, it only looks at loc.source.body.
Usage:
The reason of just wrapping the gql parsed string instead of writing a new helper that could do this in a more neat way, is that we keep all benefits that the tooling provides (including auto complete if you've configured it). :)