It was quite common for Sitecore MVC implementation to add logic around renderings that will catch unexpected exceptions in them and save your page from complete collapse. Such logic hides your component from end-users and might only put something in HTML comments, while during preview or editing experience it will give some visual indication of an error and its details. Such functionality can also be very useful for React JSS applications, but it is not that simple especially for isomorphic apps leveraging SSR (server-side rendering).

Error handling in React will be handled differently on a client and a server-side. Let’s start with the first one.

Client-side error handling

In the past, React was not very explicit about the errors and was emitting cryptic errors, but things got better with the introduction of Error Boundaries. Error Boundaries worked very similarly to the Sitecore approach defined above. They catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. It worth mentioning that Error Boundary wrapped around components will work with its lifecycle methods and constructors, but will not help you with events handlers and async code, as well as during SSR.

Server-side error handling

By design, React SSR uses supports streaming, which means that a server starts sending processed elements of your component tree through the wire while the rest is still generating HTML. That makes it impossible for Error Boundaries to hide part of a components tree where the exception happened.

The only place where you can catch errors on the server is inside a method render(). Putting try-catch in every render() method will be time-consuming and error-prone.

In case you are using Babel to process your code, you can leverage its plugin. The plugin will do the magic for you and wrap the content of all render() methods in try/catch, but I prefer to use *TypeScript *in my projects as it allows to catch many compile-time errors before the code is pushed anywhere. Mixing *TypeScript *processing with *Babel *processing is possible but not the most fun process, so I’ve ended up creating extending a PureComponent class with an error handling logic, which you can see below.

https://gist.github.com/asmagin/305d8e204dfe19cc4b9d9627f18d2fc9

The comments above will give you a pretty good understanding of what is happening. Here are some additional details.

As we do not have an option of virtual methods calling base methods, we need to have safeRender() that will be used in all derived components. In this method, you will write presentation logic. Render() method is implemented in this class and provides handling.

Before calling safeRender() in the try/catch section we are checking if a component has an error in its state. This is applicable only for the client as SSR will not call the componentDidMount() method. This will ensure that you won’t go in cycles there.

Catch{} section checking window object to understand if we are in a browser and running additional logging into a console. Both SSR and client rendering, leaving HTML comment in markup via renderErrorView(), so that you will be able to catch collapsed components. You can override this method and add your custom logic there, e.g. check if you are in the Experience editor or on the live site.

All components on the site should be inherited from this one to make it work.


As usual, follow me on Twitter @true_shoorik 😉