Relay supports many (mostly) client-only directives which help you to describe your clients needs and behavior better. They usually abstract some low-level implementation so you can easily stop using them when needed. Here is a complete list of them:
@arguments is a directive used to pass arguments to a fragment that was defined using
@argumentDefinitions. For example:
@argumentDefinitions is a directive used to specify arguments taken by a fragment. For example:
@connection effectively creates a client/local field in the graphql schema to store the merged results of the initial fetch plus pagination queries to load more edges - on the assumption that you're doing infinite scroll style. It is also possible to change the internal implementation via custom handler
@connection(handler: "..."). It's complicated but doable.
This is how default connection handler looks like.
@connection(key: "list_users", filters: )means: store the data regardless of the value of
search-- this could cause a potential problem if there are two components/views sharing the same connection and when the second view fetches the connection with
search: "foo", it will overwrite the data fetched with
search: barin the first view.
Implements support for dynamic connection keys. Relay currently supports the
keyargument to namespace the results of a connection field - but because this value is static, if multiple instances of the same component (and therefore fragment) are subscribed, they will share the underlying connection state in the store. There are some use-cases where applications would prefer to have data namespaced on a per-instance basis. We plan to investigate this in a follow-up, but as short-term solution this diff implements support for dynamic connection keys. In addition to the still-required static key, a fragment may specify
dynamicKey_UNSTABLE: $someVariable(must be a variable) whose runtime value is used to compute the storage key (in addition to the filters and static key). This is behind a feature flag as we intend to investigate alternatives in the near-term.
@defer, @stream, @stream_connection
A bit more context: as implied from the talk, at Facebook we are currently experimenting with support for
@streamdirectives in our GraphQL server and in Relay. Our plan is to get experience using these directives in our apps in order to validate the concept, iterating as appropriate. We're still early in this process and are not yet ready to begin any effort toward standardization, but we will certainly consider this as we get more experience and feel more confident in the approach.
Non-React functions can also take advantage of data masking. A fragment can be defined with the
@inline directive and stored in a local variable. The non-React function can then "unmask" the data using the
This annotation can be used to generate types (Flow/TS) for
optimisticResponse when writing mutations. Real example could look like this:
This is quite a common pattern to write data fragment only once when fetching the data (
NoteEditor_lead) and reuse it for the mutation. It's because you should always fetch the same you are mutating (and you are probably mutating the same you are just rendering). However, the generated types whould contain just the fragment reference as you know from the queries and it's not a good idea to unmask such fragments since it doesn't work recursively. Luckily, mutations with additional directive
@raw_response_type generate also raw response types. Compare these two generated types - first without the annotation:
And now with the
That's the type which is being used to annotate
optimisticResponse when you use
@refetchable(queryName: " … "), @fetchable(field_name: " … ")
For OSS: the
@fetchabledirective is for the schema SDL, not queries, and allows the schema to specify that a) a type is (re)fetchable and b) what field should be used to refetch it. For each
Foo, the schema is expected to define a field on the
Querytype that follows the convention of
fetch__Foo(<name>: ID!): Foo. This is a generalization of the pattern established with the Node interface and node() root field.
The use-case is things like utility functions that are not executing in a React context and therefore don't have access to the context's environment.
@relay(mask:false)was our earlier solution to this (which as you noted has some issues),
@inlineis its replacement.
Please note: Relay doesn't have any type information about scalar fields in the normalization ASTs (whether the filed is plural, nullable, Integer or Float, etc). In these cases cases, Relay Payload Generator defaults to String (see: https://github.com/facebook/relay/issues/2807#issuecomment-515690739). This can be solved by using
@relay_test_operation in your tests.
Generated test payload WITHOUT
Generated test payload WITH
@relay_test_operation directive (notice the highlighted changes):
@skip directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional exclusion during execution as described by the if argument.
@include directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional inclusion during execution as described by the if argument.
@include has precedence over the other. In the case that both the
@include directives are provided on the same field or fragment, it must be queried only if the
@skip condition is false and the
@include condition is true. Stated conversely, the field or fragment must not be queried if either the
@skip condition is true or the
@include condition is false.
Other internal directives
Please, read this carefully!
You should not use there directives unless you know exactly what you are doing and you are ready to face the consequences!
This directive is not intended for use by developers directly. To set a field handle in product code use a compiler plugin (source)