Aaron Vanston
Front-end developer from Melbourne, Australia.
Introduction to GraphQL
"Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data, all while automatically updating your UI."
https://www.apollographql.com/docs/react/
*Kinda, but actually a lot more
// client.js
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
export const client = new ApolloClient({
uri: 'https://graphqlserveraddress.com',
cache: new InMemoryCache()
});
client
.query({
query: gql`
query locations {
name
countryCode
}
`
})
.then(result => console.log(result));
// index.js
import React from 'react';
import { render } from 'react-dom';
import { ApolloProvider } from '@apollo/client';
import { client } from './client'
import JobLocations from './JobLocations'
const App = () => {
return (
<ApolloProvider client={client}>
<h2>My first Apollo app 🚀</h2>
<JobLocations />
</ApolloProvider>
);
}
render(<App />, document.getElementById('root'));
// JobLocations.js
import { useQuery, gql } from '@apollo/client';
const LOCATIONS = gql`
query locations {
name
countryCode
}
`;
const JobLocations = () => {
const { loading, error, data } = useQuery(LOCATIONS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return data.locations.map(({ name, countryCode }) => (
<div>
<p>{name}, {countryCode}</p>
</div>
));
}
// Fetching data immediately
// useQuery
const { loading, error, data } = useQuery(LOCATIONS);
// Fetching data manually
// useLazyQuery
const [getLocation, { loading, error, data }] = useLazyQuery(LOCATION);
getLocation({ variables: { locationId: 123 }})
// Mutating data
// useMutation
const [createQuestionnaire, { loading, error, data }] = useMutation(CREATE_QUESTIONNAIRE)
createQuestionnaire({ variables: { name: 'Product Questions', ... }})
// Streaming data, requires transport layer
// useSubscription
const { loading, error, data } = useSubscription(CANDIDATE_SUBSCRIPTION)
Apollo Client
Cache
GraphQL Server
Queries local and remote fields
Calculates local fields
Queries remote fields
Resolves remote fields
Returns remote fields
Caches remote fields
Returns ALL fields
Time passes...
Queries local and remote fields
Calculates local fields
Fetches remote fields (now cached)
Returns ALL fields
import { InMemoryCache, ApolloClient } from '@apollo/client';
const client = new ApolloClient({
// ...other arguments...
cache: new InMemoryCache(options)
});
{
"location": {
"id": "seekAnz:location:seek:2FqwWaaMV",
"__typename": "Location"
// Generates an of of "Location:seekAnz:location:seek:2FqwWaaMV"
}
}
query {
branding(id: '5') {
id
name
}
}
// Generated ID: 'Branding:5'
// Result
{
id: '5',
name: 'Primary Brand'
}
// Background task updates DB record
// Name: 'Primary Brand' -> 'Brand 1'
// Re-call result
{
id: '5',
name: 'Primary Brand'
}
mutation {
updateBranding(id: '5', name='Brand 1') {
id
name
}
}
query {
branding(id: '5') {
id
name
}
}
// Result
{
id: '5',
name: 'Brand 1'
}
const client = new ApolloClient({
link: concat(authMiddleware, httpLink),
cache: new InMemoryCache(),
defaultOptions: {
query: {
fetchPolicy: 'no-cache',
}
},
})
//...
const { loading, error, data } = useQuery(GET_BRANDINGS, {
fetchPolicy: "network-only"
});
// cache-first - DEFAULT
// cache-only
// cache-and-network
// network-only
// no-cache
// standby
https://www.apollographql.com/docs/react/data/queries/#supported-fetch-policies
query {
questionnaires {
id
name
}
}
// Result
[
{
id: '1',
name: 'Product questionnaire'
},{
id: '2',
name: 'Tech questionnaire'
}
]
const CREATE_QUESTIONNAIRE = gql`
mutation {
createQuestionnaire(name: 'UX questionnaire') {
id
name
}
}
`
const [createQuestionnaire] = useMutation(CREATE_QUESTIONNAIRE)
createQuestionnaire({
refetchQueries: ['questionnaires']
})
// query {
// questionnaires {
// id
// name
// }
// }
https://www.apollographql.com/docs/react/local-state/local-state-management/
// client.js
import { ApolloClient, InMemoryCache } from '@apollo/client';
import { gql } from '@apollo/client';
export const cache = new InMemoryCache()
export const client = new ApolloClient({
uri: 'https://graphqlserveraddress.com',
cache
});
import { useQuery } from '@apollo/client';
import { cache } from './client'
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn @client
}
`;
cache.writeQuery({
query: IS_LOGGED_IN,
data: {
isLoggedIn: !!localStorage.getItem("token"),
},
});
const App = () => {
const { data } = useQuery(IS_LOGGED_IN);
return data.isLoggedIn ? <Pages /> : <Login />;
}
import { makeVar } from '@apollo/client';
const isLoggedIn = makeVar(false);
// Output: false
console.log(isLoggedIn());
isLoggedIn(true);
// Output: true
console.log(isLoggedIn());
// ...
cache.writeQuery({
query: IS_LOGGED_IN,
data: {
isLoggedIn: isLoggedIn(),
},
});
// ...
import { useReactiveVar } from '@apollo/client';
const User = () => {
const isLoggedIn = useReactiveVar(isLoggedIn);
return isLoggedIn ? <Pages /> : <Login />;
}
Introduction to GraphQL
By Aaron Vanston