using fragment, fetchPolicy option and managing local state - geoseong/hackatalk GitHub Wiki
- Enhancing Reusability with Fragments: More GraphQL Concepts
- Previewing the Apollo Client 3 Cache
- Apollo Client(React): CACHING -> Interacting with cached data
You may have noticed that the queries for fetching a list of launches and fetching a launch detail share a lot of the same fields. When we have two GraphQL operations that contain the same fields, we can use a fragment to share fields between the two.
/* launch.tsx */
export const LAUNCH_TILE_DATA = gql`
fragment LaunchTile on Launch {
id
isBooked
rocket {
id
name
}
mission {
name
missionPatch
}
}
`;
/* otherpage.tsx */
import { LAUNCH_TILE_DATA } from './launches';
const GET_LAUNCHES = gql`
query launchList($after: String) {
launches(after: $after) {
cursor
hasMore
launches {
...LaunchTile
}
}
}
${LAUNCH_TILE_DATA}
`;
Sometimes, it's useful to tell Apollo Client to bypass the cache altogether if you have some data that constantly needs to be refreshed. We can do this by customizing the useQuery hook's fetchPolicy.
- By default, Apollo Client's fetch policy is
cache-first
, which means it checks the cache to see if the result is there before making a network request
We recommend managing local state in the Apollo cache instead of bringing in another state management library like Redux so the Apollo cache can be a single source of truth.
import gql from 'graphql-tag';
import { ApolloCache } from 'apollo-cache';
import * as GetCartItemTypes from './pages/__generated__/GetCartItems';
import * as LaunchTileTypes from './pages/__generated__/LaunchTile';
import { Resolvers } from 'apollo-client'
export const typeDefs = gql`
extend type Query {
isLoggedIn: Boolean!
cartItems: [ID!]!
}
extend type Launch {
isInCart: Boolean!
}
extend type Mutation {
addOrRemoveFromCart(id: ID!): [ID!]!
}
`;
type ResolverFn = (
parent: any,
args: any,
{ cache } : { cache: ApolloCache<any> }
) => any;
interface ResolverMap {
[field: string]: ResolverFn;
}
interface AppResolvers extends Resolvers {
// We will update this with our app's resolvers later
}
export const resolvers = {};
The only difference is that you add a @client directive to a local field to tell Apollo Client to pull it from the cache.
Since cache reads are synchronous, we don't have to account for any loading state.
import { ApolloProvider, useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import Pages from './pages';
import Login from './pages/login';
import injectStyles from './styles';
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn @client
}
`;
function IsLoggedIn() {
const { data } = useQuery(IS_LOGGED_IN);
return data.isLoggedIn ? <Pages /> : <Login />;
}
injectStyles();
ReactDOM.render(
<ApolloProvider client={client}>
<IsLoggedIn />
</ApolloProvider>,
document.getElementById('root'),
);