Error Handling using Error Boundaries in React 16

Share this video with your friends

Send Tweet

A JavaScript error in the UI shouldn’t break the whole application. To solve this problem React 16 introduced the new concept of an error boundary.

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the crashed component tree.

In this lesson we'll create an error boundary. We can use the new lifecycle hook componentDidCatch to handle any errors that the components we wrap throw at us, without unmounting our entire app!

Deniz Oguz
Deniz Oguz
~ 7 years ago

It is seems this video is starting from middle of something. I had to stop and rewind a few times to catch topic. But content is explained well. Thanks.

Gabor
Gabor
~ 7 years ago

This seems useful. Also nicely explained, thanks!

Vamshi
Vamshi
~ 7 years ago

Dumb question: Why do you do this.setState(state => {...state, hasError: true}) rather than this.setState({hasError: true}) ?

Vamshi
Vamshi
~ 7 years ago
wangshijun
wangshijun
~ 7 years ago

Great video!

jpbamberg1993
jpbamberg1993
~ 7 years ago

This is not working for me. I copied your code straight from the code pen example at the bottom. It renders the correct error message for a second the redirects to a regular error page. I created the app I am using to follow along with create-react-app. I would also like to second Vamshi's question on the ...state?

lucas
lucas
~ 7 years ago

@Nik Graf

Great lesson....

Your code editor, Seems really great, What's the editor you are using? and how did you config it? thanks~

Alan Plum
Alan Plum
~ 7 years ago

@jpbamberg1993 Try adding "type='button'" to the button. The default button type is "submit" which would cause the browser to submit the form. As the button isn't actually in a form this shouldn't do anything but your browser may disagree.

Mauro Carrero
Mauro Carrero
~ 7 years ago

This is not working for me. I copied your code straight from the code pen example at the bottom. It renders the correct error message for a second the redirects to a regular error page. I created the app I am using to follow along with create-react-app. I would also like to second Vamshi's question on the ...state?

It happens the same here, it seems that the problem is the development build, try building and running production build and it will work. It looks like the problem (or expected behaviour once you know about it) is to avoid breaking the app only in prod. If you see react-dom.development.js in the stack trace you will have the error in the screen, if you see react-dom.production.js you should not.

Regarding Vamshi's question, is preserving the state only adding the hasErrors flag.

Aman Gupta
Aman Gupta
~ 7 years ago

this.setState(state => { throw new Error("Oh nooo!"); return { ... state }; })

why return statement after throw error ? doesn't it break the execution at throw statement itself ?

Stephen
Stephen
~ 7 years ago

Where's the beginning of this, am I missing something??

Stephen
Stephen
~ 7 years ago

NIce explanation,

Melissa Clausse
Melissa Clausse
~ 7 years ago

Dumb question: Why do you do this.setState(state => {...state, hasError: true}) rather than this.setState({hasError: true}) ?

...state is called a spread operator. What it does here, is it passes the whole state object into setState, and only updates the part you want to update, hasError: true. If you did this.setState({hasError: true}), you would be replacing the entire state object with just your hasError: true line.

Read more about spread attributes in JSX over here: JSX Spread Attributes

Estefan Antelo
Estefan Antelo
~ 7 years ago

@Melissa there are no dumb questions. You are right, but I think the author intended to do just what he has done.

If you replace the state with a {hasError: true} object, you end up implicitly removing every other part of the state. The author is creating a new state based on the old but overwriting the hasError value. I think this is the most common way to update your component's state. Do you agree?

Spread Attributes make use of the Spread Operator as well, but are used in another context (passing props from an object to a subcomponent)

Here's the Specification for the Spread Operator: https://tc39.github.io/proposal-object-rest-spread/

I hope this helped you!

Kind Regards, Steve :)

Randy Creasi
Randy Creasi
~ 7 years ago

Dumb question: Why do you do this.setState(state => {...state, hasError: true}) rather than this.setState({hasError: true}) ?

...state is called a spread operator. What it does here, is it passes the whole state object into setState, and only updates the part you want to update, hasError: true. If you did this.setState({hasError: true}), you would be replacing the entire state object with just your hasError: true line.

Read more about spread attributes in JSX over here: JSX Spread Attributes

That's not correct. The object you pass to setState need only contain the state variables you want to update. The setState method does the merging of other properties for you. See https://reactjs.org/docs/react-component.html#setstate

Chetan Kantharia
Chetan Kantharia
~ 7 years ago

Do you guys has any recommendation for remote error reporting service?

Arno Lenin
Arno Lenin
~ 7 years ago

@Randy is correct,

Melissa Clausse
Melissa Clausse
~ 7 years ago

@Estefan, the "dumb question" part was a quote, I was replying to Vamshi's comment further up the thread :)

@Randy As stated in your link "Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the previous state, we recommend using the updater function form, instead". That's what I was trying to explain as the difference between

  • this.setState({hasError: true}) which is a shallow merge and overrides hasError regardless of any other calls to setState and
  • this.setState((state) => {...state, hasError: true}) where state is the previous state which ensures you're always making an update based on latest state.
Melissa Clausse
Melissa Clausse
~ 7 years ago

@Randy Sorry, I realize my original post doesn't express the above as I intended it to. Upon rereading my own block I realize it is incorrectly stating that the entire state would be overriden which is not what I meant to say. I meant to say it would be hard-overriding the state rather than taking into account previous state. My bad! Thanks for helping clarify.

Randy Creasi
Randy Creasi
~ 7 years ago

@Melissa That's a great explanation why you'd want to pass a function (instead of an object) to setState. However, even in that case it's not necessary to spread the previous state into the object that function returns. The previous state is made available to you only to enable you to calculate a new value based upon it (e.g. { counter: prevState.counter + 1 }) not because it's required (meaning { ...prevState, counter: prevState.counter + 1 } is equivalent and no more correct).

Melissa Clausse
Melissa Clausse
~ 7 years ago

@Randy Ah, I see, thank you very much - very helpful explanation. Do you know if passing a function is considered innefficient or if it can have any negative consequences? I've gotten into the habit of passing a function as shown above whenever manipulating the state but if it's unnecessary I'd prefer using the shorthand.

Randy Creasi
Randy Creasi
~ 7 years ago

@Melissa Any function call incurs a slight overhead so in a strict sense you could say it's less efficient. But, as always with optimization, it's best not to worry about that until it becomes noticeable and you've profiled your app to find the bottlenecks. In most cases it will never become an issue. At least that's what I've heard from people much smarter than me :) This inspires me to start passing a function more often!

Christian
Christian
~ 7 years ago

Any feedback from the author?!?!?