In the Node.js world, Context allows us to share data and state within the same request. In GraphQL, contexts allow data to be shared between multiple resolver functions and middleware for the same request.
A common use case is to store the identity of the current visitor in the context to be accessed in the resolver function and middleware.
In GQLoom
, we access the context through the useContext()
function.
GQLoom's useContext
function is designed to reference React's useContext
function.
You can call the useContext
function from anywhere within the resolver to access the context of the current request without explicitly passing the context
function.
Behind the scenes, useContext
uses node.js' AsyncLocalStorage to pass the context implicitly.
Next, let's try to access the context in various places. We will use graphql-yoga as an adapter.
In the code above, we use the useContext
function to get the Authorization
header of the current request from the context and concatenate it with the Hello
string.
The useContext
function accepts a generic parameter that specifies the type of the context, in this case we passed in the YogaInitialContext
type.
Let's try to call this query:
You should get the following response:
In the code above, we created a custom hook called useUser
that uses the useContext
function to get the Authorization
header of the current request from the context.
We then created a middleware called authGuard
which uses the useUser
hook to fetch the user and throw an error if the user is not logged in.
To learn more about middleware, see middleware documentation.
We can customize the validation or transformation in valibot
and access the context directly within it.
In the code above, we use useUser()
in v.transformAsync
to get the user information in the context and return it as the value of name
.
Consider that we access the user through the following custom function:
We may execute some expensive operations in useUser()
, such as fetching user information from the database, and we may also call it multiple times in the same request.
To avoid the extra overhead of multiple calls, we can use memoization to cache the results and reuse them in subsequent calls.
In GQLoom, we use the createMemoization
function to create a memoized function.
A memoization function caches its results in the context after the first call and returns the cached results directly in subsequent calls.
That is, the memoized function will only be executed once in the same request, no matter how many times it is called.
Let's memoize the useUser()
function:
As you can see, we simply wrap the function in the createMemoization
function.
We can then call useUser()
from anywhere within the resolver without worrying about the overhead of multiple calls.
In addition to the useContext
function, GQLoom provides the useResolverPayload
function for accessing all parameters in the resolver:
root: the previous object, not normally used for fields on the root query type;
args: the arguments provided for the field in the GraphQL query;
context: the context object shared across parser functions and middleware;
info: contains information about the current resolver call, such as the path to the GraphQL query, field names, etc;
field: the definition of the field being resolved by the current resolver;
In the GraphQL ecosystem, each adapter provides a different context object, and you can learn how to use it in the Adapters chapter: