MobX Depot Logo

MobX Depot

Docs

Get started
Models
Queries
Mutations
Root store
Caching
React hooks

Querying data

The Query type in your GraphQL schema contains each query that you can dispatch. mobx-depot converts each query into its own class.

For example, given the following schema:


type Query {
user(id: ID!): User
}

This will generate a UserQuery class that you can use as such:


import { UserQuery } from "~/models/depot";
const userQuery = new UserQuery(
// Query variables
{ id: 1 },
// Select the fields you want to retrieve
user => user.name.email,
// Optionally provide any applicable options, currently there's only a "cachePolicy" property:
{
// By default, the query will use the value you provided when calling initializeDepotClient
// (which defaults to "cache-and-network")
cachePolicy: "network-only"
}
);
userQuery.dispatch().then(user => {
// user is a UserModel, which is a MobX observable
// It can also be null, as described by the schema
});

If you want to re-use the same query instance, you can provide a new set of variables when calling dispatch:


userQuery.dispatch({ id: 2 })
// ...
userQuery.dispatch({ id: 3 })
// ...
userQuery.dispatch({ id: 4 })

Sometimes when instantiating a query you may not know what variables it will use. In this case you can provide null in the constructor:


const userQuery = new UserQuery(
// We don't know the query arguments yet!
null,
user => user.name.email,
);
// ... We did some stuff, and now we know what ID we want:
userQuery.dispatch({ id: 1 })

If you call dispatch without ever providing variables, it will throw an error at runtime.

Query builder

When constructing queries and mutations with mobx-depot, in order to select which fields to retrieve you need to provide a function that returns the fields you want to retrieve. Type annotations are provided for your convenience.


import { UserQuery } from "~/models/depot";
const userQuery = new UserQuery(
{ id: 1 },
user => user.name.email.createdAt.updatedAt
);

This function will generate the following document:


query UserQuery($id: ID!) {
user(id: $id) {
name
email
createdAt
updatedAt
}
}

However this can be shortened by using the primitives key, instead of listing all the fields:


const userQuery = new UserQuery(
{ id: 1 },
user => user.primitives
);

This will generate the same document.

Nested objects

Given the following schema:


type User {
name: String
email: String
address: Address
}
type Address {
street: String
city: String
country: String
}

The query builder provides functions to select fields within nested objects:


const userQuery = new UserQuery(
{ id: 1 },
user => user.name.address(address => address.street.city.country).email
);

This will generate the following document:


query UserQuery($id: ID!) {
user(id: $id) {
name
email
address {
street
city
country
}
}
}

Again, this can be shortened by using the primitives key:


const userQuery = new UserQuery(
{ id: 1 },
user => user.primitives.address(address => address.primitives)
);

Nested field arguments

Given the following schema:


type Post {
id: ID!
title: String
content: String
}
type User {
name: String
email: String
posts(limit: Int!, offset: Int): [Post]
}

You can provide an object containing arguments for the posts field:


const userQuery = new UserQuery(
{ id: 1 },
user => user.name.email.posts({ limit: 10, offset: 0 }, post => post.title.content)
);

This will generate the following document:


query UserQuery($id: ID!) {
user(id: $id) {
name
email
posts(limit: 10, offset: 0) {
title
content
}
}
}

Note: Since the limit argument in this case is non-nullable, TypeScript will enforce that you provide a value for it.