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

State empty when SSR fails because of getDataFromTree throws #1403

Open
gabriel-miranda opened this Issue Dec 12, 2017 · 7 comments

Comments

Projects
None yet
4 participants
@gabriel-miranda

gabriel-miranda commented Dec 12, 2017

Intended outcome:
SSR query fails and fills the field loading with: false, error with: <error> and the <keys> you wanted with their respective values. And doesn't run again on client side.

Actual outcome:
SSR query fails and fills the field loading with: true, error with: undefined and the <keys> you wanted with undefined.

How to reproduce the issue:
You can reproduce it here: https://github.com/gabriel-miranda/chorus/tree/develop querying a post that doesnt exist, or doing a query that fails in any server with SSR (next.js example also).
This happens because when you do:

    try {
          // Run all GraphQL queries
          await getDataFromTree(
            <ApolloProvider client={apollo}>
              <ComposedComponent url={url} {...composedInitialProps} />
            </ApolloProvider>
          );
        } catch (error) {
          // Prevent Apollo Client GraphQL errors from crashing SSR.
          // Handle them in components via the data.error prop:
          // http://dev.apollodata.com/react/api-queries.html#graphql-query-data-error
        }

File reference: https://github.com/gabriel-miranda/chorus/blob/develop/src/www/utils/withData.js

getDataFromTree throws an error and doesn't fill the apollo state needed.

Version

  • apollo-client@2.0.4
  • react-apollo@2.0.4
@gabriel-miranda

This comment has been minimized.

gabriel-miranda commented Jan 2, 2018

Any updates on this? Should I send a PR fixing this after I find out the best solution?
The issue is here:

throw error;

This breaks entirely SSR

@flipxfx

This comment has been minimized.

flipxfx commented Feb 12, 2018

What's even weirder, if you are using the next.js with-apollo example and upgrade to the latest preset, if the GraphQL server returns an error status code (like 400), the try catch does successfully catch the getDataFromTree successfully, but somehow the error is thrown later, after the try catch and the render, causing a crash :/

@dejayc

This comment has been minimized.

dejayc commented Mar 4, 2018

@flipxfx have you tried using getDataFromTree().catch(/* your callback goes here. */)

@flipxfx

This comment has been minimized.

flipxfx commented Mar 5, 2018

I using try { await getDataFromTree(...) } catch (error) {}. It catches the error there, but then throws it again somewhere along the way.

@dejayc

This comment has been minimized.

dejayc commented Mar 9, 2018

I using try { await getDataFromTree(...) } catch (error) {}. It catches the error there, but then throws it again somewhere along the way.

Maybe use a try/catch block within the catch callback to figure out what's happening.

@flipxfx

This comment has been minimized.

flipxfx commented Mar 9, 2018

Well now I can't reproduce it. I've updated quite a bit on our Apollo server and client since then so not sure what was happening.

@richardscarrott

This comment has been minimized.

richardscarrott commented Nov 6, 2018

@gabriel-miranda did you find a solution to this? Currently the only solution I can see is to handle errors differently on the server vs client, e.g.

const ProductDetailPage = () => {
    <Query query={PRODUCT_DETAIL_PAGE}>
        {({ loading, error, data }) => {
            if (loading) return 'loading...';
            // Errors are handled here, but only for the client render
            if (error) return <Status code={error.code}>{error.code === 404 ? 'Not found' : 'Server error}</Status>; 
            if (data) return <Product {...data.product} /> 
            return null;
        }}
    </Query>
}

const serverRenderer = async (req, res) => {
    const routerContext = {};
    const root = ...;
    try {
        await getDataFromTree(root);
    } catch(error) {
        // Errors have to be handled here for the server render (which a) is a different code path to the client and b) is not component specific)
        res.status(error.code).send(renderToString(<Status code={error.code}>{error.code === 404 ? 'Not found' : 'Server error}>);
        return;
    }
    const html = renderToString(root);
    res.status(routerContext.status).send(html);
}

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