Next.js: Custom componentDidCatch does not work during SSR

Created on 2 Sep 2018  路  10Comments  路  Source: vercel/next.js

Bug report

Describe the bug

It looks like React Error Boundaries are ignored during SSR, which makes it impossible to use components with componentDidCatch lifecycle methods.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Clone MWE from kachkaev/next-component-did-catch-mwe
  2. yarn
  3. yarn build && yarn start (using production mode)
  4. go to http://localhost:3000/
  5. click _open a page that contains something broken_ to go to http://localhost:3000/contains-something-broken
  6. observe Cannot read property '42' of undefined triggered from SomethingBroken and handled by CustomErrorBoundary (this is expected behavior)
  7. refresh the page to render the same component tree on the server
  8. observe next.js 500 + an error stack in CLI instead of the same result as in step 6

Expected behavior

I expected componentDidCatch inside CustomErrorBoundary to work both on the on the server, not just on the client. It seems like it's impossible to rely on React error boundaries until this is the case.

System information

  • OS: macos
  • Version of Next.js: 7.0.0-canary.8
  • Version of React.js: 16.4.2

Additional context

If componentDidCatch can be fixed in production SSR it might be worth thinking about how it could be tested in dev mode too. At the moment the error message overlay shows up regardless of componentDidCatch has worked on the client-side and it'd be great if a popup could either be completely removed or state that an exception of such kind will be mitigated in production. CRA has a similar problem as well: https://github.com/facebook/create-react-app/issues/3627

upstream

Most helpful comment

I think next.js should provide something similar to componentDidCatch but working on both server and client side. This can only be handled by code that calls render() method of react

All 10 comments

Right, I see where the limitation is coming from. Shall there be a sentence or two in README that would warn users about such behaviour? This could go to _Custom error handling_ section for instance.

It turns out that it's not practical to define componentDidCatch throughout a Next.app unless in a dynamic component that is not server-side-rendered. Am I right with this assumption?

I'll be happy to submit a PR with a little addition to README, but you are also free to do this @timneutkens.

They handle different types of errors, for example on zeit.co we report errors in componentDidCatch of _app.js + we report in getInitialProps of pages/_error.js (this is called for pretty much every error that happens on SSR)

I also have a similar setup: componentDidCatch in pages/_app.js reports the event to Google Analytics and getInitialProps in pages/_error.js helps style the error depending on its kind (_product not found_ is not the same as _random page not found_).

Here's a scenario that does not work though: imagine we have some user-defined JSON that describes a data vis (e.g. vega or a custom one). This JSON gets passed to a React component, which tries to render an SVG. If a JSON is faulty, an error is thrown and this is where a local componentDidCatch would really shine. I tried throwing from a render function inside such a vis component and catching this error with componentDidCatch one component up, but instead the server was rendering pages/_error.js, which is not what I expected. When a page with the vis was loaded dynamically by clicking on <Link />, the local componentDidCatch did work (although the page got covered with a call stack panel in dev).

Warning others that local componentDidCatch cannot be used during SSR is what I'm talking about.

I think next.js should provide something similar to componentDidCatch but working on both server and client side. This can only be handled by code that calls render() method of react

What is this line doing?

super.componentDidCatch(error, errorInfo) 

Is it possible to give up SSR and retry rendering on client side when an error was thrown during SSR?

I liked @morokosi solution of sending down the JS bundle without SSR. This allows the app to handle errors on the client like it normally would.

Is it possible to give up SSR and retry rendering on client side when an error was thrown during SSR?

Or at least make such a feature opt-in

Or some page configuration to retry during hydration when a markup error happens on SSR.

download (1)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sospedra picture sospedra  路  3Comments

kenji4569 picture kenji4569  路  3Comments

jesselee34 picture jesselee34  路  3Comments

ghost picture ghost  路  3Comments

rauchg picture rauchg  路  3Comments