Records in ReasonML are nominally typed. Even if a records contains exactly the
same fields as another record, it will be seen as a different type, and they are
not compatible. That means that if you want to create an
User, you'd be able to accept for instance
UserQuery.t_user as an
argument. That's all great, but what if you have another query where you also
would like to create an avatar. In most cases Fragments are the solution here.
With fragments you can define reusable pieces that can be shared between queries. You can define a fragment in the following way
This generates the module
Avatar_User as the fragment. The
Avatar_User.t which include all the fields of the fragment.
How to we get this from the query? When you use the spread operator with the
module name, an extra field is created on the
t_user record with the name
avatar_User (same as the fragment module name but with a lowercase first
letter). This is the value that has the type
Avatar_User.t containing all the
If you want to change the default name of the fragment you can use a GraphQL
When there is just the fragment spread and no other fields on an object, there is no special field for the fragment necessary. So if this is the query:
user will be of the type
Referencing fragments from other modules
Often, you'll want to reference a fragment in a different module, so that you can compose it into a query that's defined with a different component. When doing so, you must use the same name for the fragment in the GraphQL document as you gave it where you defined it - you can't rename it.
One way to achieve this is to define a new aliased module with the same name:
Alternatively, you can also
open the module containing the fragment where it's
being used, and reference it like this:
Variables within fragments
Sometimes fragments need to accept variables. Take our previous fragment. If we would like to pass the pixelRatio as a variable as it might vary per device. We can do this as follows:
To be able to typecheck these variables and make sure that the types are
correct, there are no unused variables or variables that are not defined, we
introduce two directives here
arguments, these are
they have nothing to do with the relay client (we just re-use this convention).
Note that you cannot rename variables in the
@arguments directive so the name
of the variable and the name of the key must be the same. This is because
graphql-ppx does not manipulate variable names and just makes use of the fact
that fragments can use variables declared in the query.
There is a compile error raised if you define variables that are unused. If you (temporarily) want to define unused variables you can prepend the variable name with an underscore.
An ecape hatch for when you don't want
graphql-ppx to create a record type,
you can supply one yourself. This also makes reusability possible. We recommend
fragments however in most cases as they are easier to work, are safer and don't
require defining separate types.