ApolloReactOffline
ApolloReactOffline copied to clipboard
Unable to stringify context to JSON
First of all, thanks for the detailed tutorial on codeburst
But I'm experiencing a major issue with stringifying context when working with offline mutations. This happens on line 16 in the file src/utils/trackerLink.ts
. This line throws an error about not being about circular dependency. When I console logged the context I found that it had lots of properties and methods, of which I can't know exactly what is causing the problem.
const context = operation.getContext();
const contextJSON = JSON.stringify(context); // this fails with Unhandled Rejection (Error): Converting circular structure to JSON
I'm working with apollo-client 3.1.4.
hey @chidimo
did you happen to find a solution for this?
:)
Hello @sajadghawami I think the problem is related to the fact that the apollo cache has changed very much from when this was written. I ended up taking the cache apart and using what I need. I am using redux toolkit with redux persist to persist the mutations. Works on react-native too.
. So here's what I did to save the mutation info.
import { ApolloLink } from '@apollo/client';
import { v4 as uuidv4 } from 'uuid';
import {
saveTrackedQuery,
removeTrackedQuery,
} from '../store/trackedMutations';
export const mutationTrackerLink = (dispatch: any): any =>
new ApolloLink((operation, forward) => {
if (forward === undefined) {
return null;
}
const id = uuidv4();
const name = operation.operationName;
const queryJSON = JSON.stringify(operation.query);
const variablesJSON = JSON.stringify(operation.variables);
operation.setContext({ start: new Date() });
const context = { ...operation.getContext() };
delete context.cache;
delete context.getCacheKey;
delete context.clientAwareness;
const contextJSON = JSON.stringify(context);
if (context.tracked !== undefined) {
const payload = {
id,
name,
queryJSON,
contextJSON,
variablesJSON,
};
dispatch(saveTrackedQuery(payload));
}
return forward(operation).map((data: any) => {
if (context.tracked !== undefined) {
dispatch(removeTrackedQuery(id));
}
const time = new Date().getTime() - operation.getContext().start;
data.requestCompletionTime = time;
return data;
});
});
Here's where I'm doing the actual mutation using the save information.
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useApolloClient } from '@apollo/client';
import { getOnlineState } from '../store/online';
import {
getTrackedQueries,
removeTrackedQuery,
} from '../store/trackedMutations';
import { updateHandlerByName } from '../updateHandlers/createHandlers';
export const useTrackedQueries = () => {
const dispatch = useDispatch();
const apolloClient = useApolloClient();
const isOnline = useSelector(getOnlineState);
const trackedMutations = useSelector(getTrackedQueries);
useEffect(() => {
const execute = async () => {
const promises: any = [];
trackedMutations.forEach((trackedQuery: any) => {
const query = JSON.parse(trackedQuery.queryJSON);
const context = JSON.parse(trackedQuery.contextJSON);
const variables = JSON.parse(trackedQuery.variablesJSON);
promises.push(
apolloClient.mutate({
context,
variables,
mutation: query,
optimisticResponse: context.optimisticResponse,
update: updateHandlerByName[trackedQuery.name],
})
);
dispatch(removeTrackedQuery(trackedQuery.id));
});
if (isOnline) {
try {
await Promise.all(promises);
} catch (e) {
// ALLOW TRACKED QUERIES TO FAIL
}
}
};
execute();
}, [ isOnline ]);
return {};
};
Sorry if this is too much info. Its just that I like giving as much context as possible.
@chidimo
thank you very much for the quick reply!
I ended up using apollo-link-offline.
It seems to work so far :)
Sure @sajadghawami I'll take a look at it. I like that "it assumes the worst". Lol
@chidimo
just wanted to update you, apollo-link-offline seems to be buggy so i ended up using your version!
Thanks again :)