|
Rest is now vintage -
separated endpoint with separated entities
REST cons:
- it provides deterministic
URIs,
- caching on the HTTP level
GraphQL supports
reactive subscription data aggregation that doesn't really fit REST
architecture that well. With GraphQL, we
need only one. As the name implies, GraphQL is a graph query language that
changes the way you think of data. Instead of operating separated entities, you
start to operate on data graphs. Let's take a closer look:
|
|
Operation pattern
GraphQL provides
three operation types:
- Query
- Mutation
- Subscription
op_type Op_Name (op_params) {
field_1
field_2 (field_params) {
subfields
}
}
|
|
Query
query UserQuery ($id: Int!) {
user (id: $id) {
name
email
}
}
|
|
Mutation
mutation UserNameMutation ($id: Int!, name: String!) {
editUserName (id: $id, name: $name) {
name
}
}
|
|
Subscription
subscription UserQuery ($id: Int!) {
user (id: $id) {
name
email
}
}
|
|
|
Shopping cart example
|
|
Shopping Cart Query
query ShoppingCartList {
products {
id
title
preview
price
}
}
|
Details query
query ProductInfo($id: Int!) {
product(id: $id) {
id
title
preview
price
isAvailable
discountValue
description
}
}
|
We can now utilise reusable fragments
|
|
Define
fragment preview on Product {
title
preview
price
}
|
Define
fragment details on Product {
isAvailable
discountValue
description
}
|
Use
query ShoppingCartList {
products {
id
...preview
}
}
|
Use
query ProductInfo($id: Int!) {
product(id: $id) {
id
...preview
...details
}
}
|
|
|
But this is going to fetch - from the web
|
fragments can be cached separately.
so they can save transfer bandwidth.
|
1. readQuery
|
const { todo } = client.readQuery({
query: gql`
query Product($id: Int!) {
product(id: $id) {
title
preview
}
}
`,
variables: { id: 5 }
});
|
2. readFragment
|
const todo = client.readFragment({
id: 5,
fragment: gql`
fragment productFragment on Product {
title
preview
}
`,
});
|
Memory cache
|
Only reads from local storage but will fail if some of the query is missing .
|
3. <Query fetchPolicy="cache-only" />
Only reads from local storage but will fail if some of the query is missing
|
<Query
query={cacheQuery}
variables={{ id }}
fetchPolicy="cache-only"
>
{({ data = {} }) => <SomeComponent />
</Query>
|
for example: Shopping List screen
|
<Query query={shoppingCartList}>
{({ loading, data }) => (
<View>
{loading && <Loading />}
{!loading && <Products data={data.products} />}
</View>
)}
</Query>
|
But we want to get some data from local cache
and some from the server
|
|
|
|
1. Cached data query
query ProductInfoCache($id: Int!) {
product(id: $id) {
id
...preview
}
}
|
And display via
<Query
query={productInfoCache}
variables={{ id }}
fetchPolicy="cache-only"
>
{({ data = {} }) => // ...
</Query>
|
|
|
2. Missing (details) data query
query ProductInfo($id: Int!, $full: Boolean!) {
product(id: $id) {
id
...preview @include(if: $full)
...details
}
}
|
Or Declaratively
<Query
query={productInfo}
variables={{ id, full: !data.product }}
>
({ loading, data }) => //...
</Query>
|
Add cache redirect
const cache = new InMemoryCache({
cacheRedirects: {
Query: {
product: (_, { id }) =>
toIdValue(cache.config.dataIdFromObject({
__typename: "Product", id
})
)
}
}
});
|
TRY IT OUT
|
|
Optimistic response … Every mutation or update - update is called
Optimistic UIs don’t wait for an operation to finish to update to the final state.
They immediately switch to the final state, showing fake data for the time while the real operation is still in-progress.
|
Remove item form the cached list
mutate({
variables: { id },
optimisticResponse: {
__typename: 'Mutation',
removeCartItem: {
__typename: 'Product',
},
},
update: (proxy) => {
const data = proxy.readQuery({ query: ShoppingCartList });
const filteredProducts = data.products.filter(product => product.id !== id);
proxy.writeQuery({
query: ShoppingCartList,
data: {...data, products},
});
},
});
|
Comments
Post a Comment