Skip to content

Instantly share code, notes, and snippets.

@jonesaustindev
Last active October 19, 2022 06:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jonesaustindev/f0cecd461e5775e6decd75c338aac994 to your computer and use it in GitHub Desktop.
Save jonesaustindev/f0cecd461e5775e6decd75c338aac994 to your computer and use it in GitHub Desktop.
React Native + Apollo Client - Offline Mutations (Blog post: https://teamairship.com/offline-first-approach-for-mobile-apps-react-native-and-apollo/)
import AsyncStorage from '@react-native-community/async-storage';
import { persistCache } from 'apollo-cache-persist';
import {
ApolloClient,
ApolloLink,
createHttpLink,
InMemoryCache,
} from '@apollo/client';
import Config from 'react-native-config';
import { setContext } from '@apollo/client/link/context';
const uri = Config.API_URL;
export const getApolloClient = async (token, queueLink) => {
const cache = new InMemoryCache({});
const httpLink = createHttpLink({
uri,
});
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
};
});
const link = ApolloLink.from([
queueLink,
authLink,
httpLink,
]);
await persistCache({
cache,
storage,
});
return new ApolloClient({ cache, link });
};
import React, { useState, useEffect } from 'react';
import { View, Text } from 'react-native';
import { ApolloProvider } from '@apollo/client';
import NetInfo from '@react-native-community/netinfo';
import QueueLink from 'apollo-link-queue';
import AsyncStorage from '@react-native-community/async-storage';
import { getApolloClient } from '../apollo/apolloClient';
import NoteView from './NoteView';
const getToken = async () => {
return await AsyncStorage.getItem('@auth_token');
};
const queueLink = new QueueLink();
const App = () => {
const [client, setClient] = useState(null);
const initializeApolloClient = async () => {
await getToken().then(async (authToken) => {
if (authToken) {
await getApolloClient(authToken, queueLink).then((apolloClient) => {
setClient(apolloClient);
});
}
});
};
useEffect(() => {
const unsubscribe = NetInfo.addEventListener((state) => {
if (state.isConnected) {
queueLink.open();
} else {
queueLink.close();
}
});
return () => unsubscribe();
}, []);
useEffect(() => {
initializeApolloClient();
}, []);
if (!client) {
return (
<View>
<Text>Loading...</Text>
</View>
);
}
return (
<ApolloProvider client={client}>
<NoteView />
</ApolloProvider>
);
};
export default App;
// Imports
const GET_NOTES = gql`
query GetNotes($employeeId: ID!) {
notes(employeeId: $employeeId) {
nodes {
content
id
name
}
}
}
`;
const NoteView = () => {
// ...
const [
createNote,
{ error: createError, data: createData, loading: createLoading },
] = useMutation(CREATE_NOTE, {
// The note variable is defined by the server I am connected to.
// Input your variables here
variables: {
note: {
employeeId: employee.id,
name: noteName,
content: noteContent,
},
},
optimisticResponse: {
__typeName: 'Mutation',
createNote: {
__typename: 'CreateNotePayload',
note: {
__typeName: 'Note',
// Input your variables here
id: getUniqueId(),
name: noteName,
content: noteContent,
},
errors: [],
},
},
update: (cache, { data }) => {
try {
const readData: any = cache.readQuery({
query: GET_NOTES,
variables: { employeeId: employee.id },
});
let mergedNotes = [];
if (readData.notes.nodes.length <= 0) {
mergedNotes = [data.createNote.note];
} else {
mergedNotes = [
data.createNote.note,
...readData.notes.nodes,
];
}
cache.writeQuery({
query: GET_NOTES,
variables: { employeeId: employee.id },
data: {
// this data object is the same as the one in the gql query above
...readData,
notes: {
nodes: mergedNotes,
},
},
});
} catch (e) {
console.log({ e });
}
},
});
// ...
}
export default NoteView;
@sajadghawami
Copy link

thank u very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment