Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

SSR: error render props do not be passed into <Query /> as expected (errorPolicy: 'all') #2134

Closed
chentsulin opened this issue Jun 24, 2018 · 2 comments · Fixed by #2753
Closed

Comments

@chentsulin
Copy link
Contributor

chentsulin commented Jun 24, 2018

I built a codesandbox app (https://codesandbox.io/s/r7mxnx486q) and a next ssr app(https://github.com/chentsulin/react-apollo-issue) to confirm that they have totally different behavior when rendering the error.

For demo, I use following code exmaple

function App() {
  return (
    <div className="App">
      <ApolloProvider client={client}>
        <Query query={Hello}>
          {({ data, error, loading }) => {
            console.log({ data, error, loading });
            if (loading) return "loading..";
            if (error) return error.message;
            return data.hello;
          }}
        </Query>
      </ApolloProvider>
    </div>
  );
}

And a launchpad to throw a error in Hello query:

https://launchpad.graphql.com/kqrn1n1qj7

Client Side Rendering

(example: https://codesandbox.io/s/r7mxnx486q)

It works as expected in client side rendering.

Props were logged twice with following format (got error in second time rendering):

{ data: {}, error: undefined, loading: true }
{ data: undefined, error: ApolloError, loading: false }

Server Side Rendering

(example: https://github.com/chentsulin/react-apollo-issue)

Props were logged twice with no error:

{ data: { hello: null }, error: undefined, loading: false }
{ data: { hello: null }, error: undefined, loading: false }

Relevant Issues

apollographql/apollo-link#437
apollographql/apollo-client#2880
#2124
#2087
#1389

I dived into source of <Query />, and logged some details. I found that it call watchQuery twice and create two different queryIds.

initializeQueryObservable watchQuery - queryId { queryId: '1' }
fetchData watchQuery - queryId { queryId: '2' }

Then it save errors into queryId: 2

queryStore.markQueryResult { queryId: '2',
  result:
   { data: { hello: null },
     errors: [ [Object] ] }

And finally it found queryStoreValue from queryId: 1 but store only have value for queryId: 2, so it pass undefined as result to render props:

queryId { queryId: '1' }
getStore { '2':
   { document: { kind: 'Document', definitions: [Array], loc: [Object] },
     previousVariables: null,
     networkError: null,
     graphQLErrors: [ [Object] ],
     networkStatus: 7,
     metadata: null } }
{ queryStoreValue: undefined }

what is the purpose of those two queryObservable? It is a little confusing.

react-apollo/src/Query.tsx

Lines 183 to 189 in 3985b47

const observable = this.client.watchQuery({
...opts,
fetchPolicy,
});
const result = this.queryObservable!.currentResult();
return result.loading ? observable.result() : false;

@kasbah
Copy link

kasbah commented Jul 3, 2018

Dupe of #1972 (and #1781?)

@tobobo
Copy link

tobobo commented Dec 14, 2018

I've opened a PR to fix the docs with respect to this issue apollographql/apollo-client#4237

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants