the stuff no-one ever told ya

Apollo Client

Alexey Kureev

@kureevalexey

op_type Op_Name (op_params) {
  field_1
  field_2 (field_params) {
    subfields
  }
}

Operation pattern

Used to retrieve information from the server

query UserQuery ($id: Int!) {
  user (id: $id) {
    name
    email
  }
}

Used to alternate information on the server

mutation UserNameMutation ($id: Int!, name: String!) {
  editUserName (id: $id, name: $name) {
    name
  }
}

Used to subscribe to event-based updates from the server

subscription UserQuery ($id: Int!) {
  user (id: $id) {
    name
    email
  }
}
query ShoppingCartList {
  products {
    id
    title
    preview
    price
  }
}
query ShoppingCartList {
  products {
    id
    title
    preview
    price
  }
}
query ProductInfo($id: Int!) {
  product(id: $id) {
    id
    title
    preview
    price
    isAvailable
    discountValue
    description
  }
}
query ShoppingCartList {
  products {
    id
    title
    preview
    price
  }
}
query ProductInfo($id: Int!) {
  product(id: $id) {
    id
    title
    preview
    price
    isAvailable
    discountValue
    description
  }
}
query ShoppingCartList {
  products {
    id
    title
    preview
    price
  }
}
query ProductInfo($id: Int!) {
  product(id: $id) {
    id
    title
    preview
    price
    isAvailable
    discountValue
    description
  }
}
fragment preview on Product {
  title
  preview
  price
}
fragment details on Product {
  isAvailable
  discountValue
  description
}
query ShoppingCartList {
  products {
    id
    ...preview
  }
}
query ProductInfo($id: Int!) {
  product(id: $id) {
    id
    ...preview
    ...details
  }
}
{
  "ROOT_QUERY": {
    "product({\"id\":\"1\"})": {
      "type": "id",
      "id": "Product:1",
      "generated": false
    }
  },
  "Product:1": {
    "id": 1,
    "title": "wheel",
    "preview": "...",
    "price": 50,
    "__typename": "Product",
    "isAvailable": true,
    "discountValue": 29.99,
    "description": "vroom vroom, check out these wheels"
  }
}

1. readQuery

const { todo } = client.readQuery({
  query: gql`
    query Product($id: Int!) {
      product(id: $id) {
        title
        preview
      }
    }
  `,
  variables: { id: 5 }
});

1. readQuery

2. readFragment

const todo = client.readFragment({
  id: 5, 
  fragment: gql`
    fragment productFragment on Product {
      title
      preview
    }
  `,
});

3. <Query fetchPolicy="cache-only" />

<Query 
  query={cacheQuery} 
  variables={{ id }}
  fetchPolicy="cache-only"
>
  {({ data = {} }) => <SomeComponent />
</Query>
<Query query={shoppingCartList}>
  {({ loading, data }) =>  (
    <View>
      {loading && <Loading />}
      {!loading && <Products data={data.products} />}
    </View>
  )}
</Query>

Shopping List screen

<Query query={productInfoQuery} variables={{ id }}>
  {({ loading, data }) =>  (
    <View>
      {loading && <Loading />}
      {!loading && <ProductInfo {...data.product} />}
    </View>
  )}
</Query>

Product Info screen

So we split our initial details query into:

1. Query to get cached data

2. Query to get additional data

<Query 
  query={productInfoCache} 
  variables={{ id }} 
  fetchPolicy="cache-only"
>
  {({ data = {} }) => // ...
</Query>
query ProductInfoCache($id: Int!) {
  product(id: $id) {
    id
    ...preview
  }
}

1. Query to get cached data

<Query 
  query={productInfo}
  variables={{ id, full: !data.product }}
>
  ({ loading, data }) => //...
</Query>
query ProductInfo($id: Int!, $full: Boolean!) {
  product(id: $id) {
    id
    ...preview @include(if: $full)
    ...details
  }
}

2. Query to get additional data

const cache = new InMemoryCache({
  cacheRedirects: {
    Query: {
      product: (_, { id }, { getCacheKey }) => 
        getCacheKey({ __typename: 'Product', id })
    }
  }
});

Add cache redirect

Try it out:

https://codesandbox.io/s/mmpm32j7ly

Apollo Client: the stuff no-one ever told ya [short]

By Alexey Kureev

Apollo Client: the stuff no-one ever told ya [short]

  • 745
Loading comments...

More from Alexey Kureev