Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query is empty after 2nd mutation update with optimisticResponse #567

Open
roballsopp opened this issue Jun 1, 2020 · 0 comments
Open
Labels
to-be-reproduced We need to reproduce this issue

Comments

@roballsopp
Copy link

roballsopp commented Jun 1, 2020

Do you want to request a feature or report a bug?
Report a bug

I'm trying to implement an optimistic response and cache update for one of my queries in my react native app so I can support offline use, but I'm running into an issue when using this workflow while the device still has service. I can see my mutation updater fire twice, as expected. The first time it fires it puts the optimistic response into the cache and the query component with the query I am updating re-renders correctly, as far as I can tell. The second time the updater fires (to update the cache with the actual server response) the part of the query I am updating comes out of the query component as null even though I have observed inside my updater the response from the server is identical to my optimistic response. I even find the query correctly after the update by querying the cache for it again inside the updater (see below).

This issue does not occur when I use import { ApolloClient } from 'apollo-client'; (I didn't install a different version, its the 2.4.6 version brought in by appsync). It only occurs when using import AWSAppSyncClient from 'aws-appsync';

Here's my code:

// SurveyQueryContainer.js
import React from 'react';
import PropTypes from 'prop-types';
import { Query } from 'react-apollo';
import SurveyNavigator from './SurveyNavigator';
import { SurveyQueryContainerQuery } from './graphql/SurveyQueryContainer';

export default function SurveyQueryContainer({ route, navigation }) {
	const { surveyTemplateId, surveyResponseId } = route.params;

	return (
		<Query
			variables={{ surveyTemplateId, surveyResponseId }}
			query={SurveyQueryContainerQuery}>
			{({ loading, error, data, refetch }) => {
                                // data.getSurveyResponse is null after the 2nd mutation updater call
				return <SurveyNavigator surveyTemplate={data.getSurveyTemplate} surveyResponse={data.getSurveyResponse} />;
			}}
		</Query>
	);
}
// SurveyQueryContainer.js
import gql from 'graphql-tag';
import { SurveyNavigatorFragments } from '../SurveyNavigator';

export const surveyTemplateFragment = gql`
	fragment SurveyQueryContainer_surveyTemplate on SurveyTemplate {
		id
		name
		...SurveyNavigator_surveyTemplate
	}
	${SurveyNavigatorFragments.surveyTemplate}
`;

export const surveyResponseFragment = gql`
	fragment SurveyQueryContainer_surveyResponse on SurveyResponse {
		id
		...SurveyNavigator_surveyResponse
	}
	${SurveyNavigatorFragments.surveyResponse}
`;

export const SurveyQueryContainerQuery = gql`
	query SurveyQueryContainerQuery($surveyTemplateId: ID!, $surveyResponseId: ID!) {
		getSurveyTemplate(id: $surveyTemplateId) {
			...SurveyQueryContainer_surveyTemplate
		}
		getSurveyResponse(id: $surveyResponseId) {
			...SurveyQueryContainer_surveyResponse
		}
	}
	${surveyTemplateFragment}
	${surveyResponseFragment}
`;
// The mutation config
import gql from 'graphql-tag';
import * as SurveyQueryContainerGql from '../../Survey/graphql/SurveyQueryContainer';

export const createSurveyResponseMutation = gql`
	mutation createSurveyResponse($input: CreateSurveyResponseInput!) {
		createSurveyResponse(input: $input) {
			id
			surveyTemplateId
			...SurveyQueryContainer_surveyResponse
		}
	}
	${SurveyQueryContainerGql.surveyResponseFragment}
`;

export const getCreateSurveyResponseMutationConfig = ({ variables }) => ({
	mutation: createSurveyResponseMutation,
	variables,
	optimisticResponse: {
		createSurveyResponse: {
			...variables.input,
			__typename: 'SurveyResponse',
			questionResponses: { __typename: 'ModelQuestionResponseConnection', items: [] },
		},
	},
	update: (store, { data: { createSurveyResponse } }) => {
                // createSurveyResponse looks exactly as I expect during BOTH updates
		let getSurveyTemplate;
		try {
			getSurveyTemplate = store.readFragment({
				id: `SurveyTemplate:${createSurveyResponse.surveyTemplateId}`,
				fragment: SurveyQueryContainerGql.surveyTemplateFragment,
				fragmentName: 'SurveyQueryContainer_surveyTemplate',
			});
		} catch (e) {
			console.warn("Could not read survey template from store", e);
		}

		store.writeQuery({
			query: SurveyQueryContainerGql.SurveyQueryContainerQuery,
			variables: {
				surveyTemplateId: createSurveyResponse.surveyTemplateId,
				surveyResponseId: createSurveyResponse.id,
			},
			data: {
				getSurveyTemplate,
				getSurveyResponse: createSurveyResponse,
			},
		});

		// const result = store.readQuery({
		// 	query: SurveyQueryContainerGql.SurveyQueryContainerQuery,
		// 	variables: {
		// 		surveyTemplateId: createSurveyResponse.surveyTemplateId,
		// 		surveyResponseId: createSurveyResponse.id,
		// 	},
		// });
		//
		// console.log('ITS ALWAYS CORRECT HERE!', result.getSurveyResponse);
	},
});

What is the expected behavior?
That data.getSurveyResponse is not null after the response from the server

Which versions and which environment (browser, react-native, nodejs) / OS are affected by this issue? Did this work in previous versions?
React Native + Expo (iOS and Android)

// package.json
{
    ...
    "aws-amplify": "^3.0.10",
    "aws-appsync": "^3.0.3",
    "aws-appsync-react": "^3.0.3",
    ...
    "expo": "^36.0.0",
    ...
    "react": "~16.8.3",
    "react-apollo": "~2.4.1",
    "react-native": "~0.61.0",
    ...
}

Unknown if it works in other versions

@sammartinez sammartinez added the to-be-reproduced We need to reproduce this issue label Jun 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
to-be-reproduced We need to reproduce this issue
Projects
None yet
Development

No branches or pull requests

2 participants