2

I have a component that I'd like to fetch data for a profile and allow posting messages on the same view. I've created a simple profile component here, and have the mutation set within the query, similar to the Apollo React tutorial.

When I run this, I get a properly rendered query with data. When the button is pressed, the mutation occurs but the page re-renders with an empty object in the Query's data parameter and the page errors with Cannot read property 'name' of undefined (which is expected given a blank data object).

Is there a better approach here?

const GET_PROFILE = gql`
  query GetProfileQuery($profileId: ID!) {
    getProfileInfo(profileId: $profileId) {
      name
    }
  }
`;

const ADD_ENDORSEMENT = gql`
  mutation AddEndorsement($profileId: ID!, $body: String!) {
    addEndorsement(profileId: $profileId, body: $body) {
      endorsementId
    }
  }
`;

const Profile = props => {
  const profileId = props.match.params.profileId;
  return (
    <Query query={GET_PROFILE} variables={{ profileId: profileId }}>
      {({ loading, error, data }) => {
        if (loading) return <p>Loading...</p>;
        if (error) return <p>Error :(</p>;
        return (
          <Fragment>
            <h1>Welcome {data.getProfileInfo.name}</h1>
            <Mutation mutation={ADD_ENDORSEMENT}>
              {(addEndorsement, { loading, error }) => (
                <div>
                  <button
                    onClick={e => {
                      addEndorsement({
                        variables: {
                          profileId: profileId,
                          body: "This is a test."
                        }
                      });
                    }}
                  >
                    Save
                  </button>
                  {loading && <p>Loading...</p>}
                  {error && <p>Error :(</p>}
                </div>
              )}
            </Mutation>
          </Fragment>
        );
      }}
    </Query>
  );
};
1

2 Answers 2

1

I had a similar issue were data turned up undefined. In my case the problem was caused by a Query subscribeToMore option I was using invalidating the cache by silently failing to merge the updated data into the original Query results (it did not contain exactly identical data fields).

The question doesn't mention subscriptions, but it will be a similar cache invalidation problem.

To fix I'd first try making sure the Query and Mutation's return identical data.

If that doesn't resolve, then depending on responsiveness needs either look at the "refetchQueries/awaitRefetchQueries" to refresh the Query, or manually poking the updated data into the local cache with "update" options on the Mutation.

Good luck.

Sign up to request clarification or add additional context in comments.

Comments

0

Try adding the following to the onClick mutation, it should help avoid needing to update the cache manually, although that would be the next step. You can pass just the string name of the query to refetchQueries, you don't need to pass the actual query there. Another trick is to ensure you are getting the same fields back so the cache object matches, (not sure what type you are returning on the query/mutation.

onClick={e => {
  addEndorsement({
    variables: {
      profileId: profileId,
      body: 'This is a test.',
    },
    refetchQueries: ['GetProfileQuery']
  })
}}

1 Comment

But this time 2 network request will be done. So i do not think so this is the best practise..!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.