graphQLSelector()
graphQLSelector()
creates a Recoil selector which syncs with the provided Relay environment and GraphQL query or subscription. The selector will automatically update with any deferred data, live queries, or if any local commits or updates are performed which mutate that part of the graph. The selector acts like a local cache with the server as the source of truth. It is writable and can be configured to commit mutations to the server when updated as a write-through cache.
If you would like to pass a parameter from the consumer callsite to the query variables consider graphQLSelectorFamily()
.
function graphQLSelector<
TVariables: Variables,
TData: $ReadOnly<{[string]: mixed}>,
T = TData,
TRawResponse = void,
TMutationVariables: Variables = {},
TMutationData: $ReadOnly<{[string]: mixed}> = {},
TMutationRawResponse = void,
>({
key: string,
environment: IEnvironment | EnvironmentKey,
query:
| Query<TVariables, TData, TRawResponse>
| GraphQLSubscription<TVariables, TData, TRawResponse>,
variables:
| TVariables
| (({get: GetRecoilValue}) => (TVariables | null)),
mapReponse: (TData, {get: GetRecoilValue, variables: TVariable}) => T,
default?: T,
mutations?: {
mutation: Mutation<TMutationVariables, TMudationData, TMutationRawResposne>,
variables: T => TMutationVariables | null,
},
}): RecoilState<T>
key
- A unique string used to identify the selector.environment
- The Relay Environment or anEnvironmentKey
to match with an environment pprovided by a surrounding<RecoilRelayEnvironment>
.query
- A GraphQL Query or Subscription. Fragments are supported in queries.variables
- Callback to provide the variables object to use for the query. This may be the variables object directly or a callback which has aget()
function that allows the selector to reference other upstream Recoil atoms/selectors. Ifnull
is provided as the variables then no query will be performed and thedefault
value will be used instead.mapResponse
- Callbak to transform the GraphQL results for using as the value of the selector. It is also provided aget()
function so it can reference other Recoil atoms/selectors to perform the transformation.default
- The default value to use ifnull
is provided as thevariables
. Ifdefault
is not provided then the selector will remain in a pending state.mutations
- Optional configuration of a GraphQL Mutation and variables to commit if the selector is explicitly written to.
Simple Example​
const eventQuery = graphQLSelector({
key: 'EventQuery',
environment: myEnvironment,
query: graphql`
query MyEventQuery($id: ID!) {
myevent(id: $id) {
id
name
}
}
`,
variables: {id: 123},
mapResponse: data => data,
});
Query Based on Recoil State​
The variables
used for the query can depend on other upstreeam Recoil State. The query will subscribe to this upstream state and will automatically update if the upstream state is changed.
const eventQuery = graphQLSelector({
key: 'EventQuery',
environment: myEnvironment,
query: graphql`
query MyEventQuery($id: ID!) {
myevent(id: $id) {
id
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data.myevent,
});
Transform Response​
The response from the server can be transformed for the value to use for the selector by using the mapResponse
option.
const eventNameQuery = graphQLSelector({
key: 'EventNameQuery',
environment: myEnvironment,
query: graphql`
query MyEventQuery($id: ID!) {
myevent(id: $id) {
id
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data.myevent?.name,
});
The transformation can also reference other Recoil atoms/selectors. It will subscribe to that upstream state and automatically update if the upstream state changes.
const eventNameQuery = graphQLSelector({
key: 'EventNameQuery',
environment: myEnvironment,
query: graphql`
query MyEventQuery($id: ID!) {
myevent(id: $id) {
id
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: (data, {get}) => get(prefixAtom) + ':' + data.myevent?.name,
});
Skip Query​
Because the variables can depend on dynamic upstream state it is possible that for some states you may not wish to issue a query. You can always avoid a query from being issued by returning null
for the variables
. In this case the default
value will be used. If no default
is provided then the selector will remain in a pending state.
const eventNameQuery = graphQLSelector({
key: 'EventNameQuery',
environment: myEnvironment,
query: graphql`
query MyEventQuery($id: ID!) {
myevent(id: $id) {
id
name
}
}
`,
default: 'PLACEHOLDER NAME',
variables: ({get}) => {
const id = get(currentIDAtom);
if (!isIDValid(id)) {
return null;
} else {
return {id};
}
},
mapResponse: data => data.myevent?.name,
});
GraphQL Fragments​
GraphQL fragments are also supported in queries.
Mutations​
graphQLSelector()
acts as a local cache for the GraphQL server state as the source of truth. It is writable and can be configured to commit a mutation to the server if written to. See the write-through cache example.