This course has been updated! We now recommend you take the Complete Intro to React, v8 course.
Transcript from the "Error Boundaries" Lesson
[00:00:00]
>> So this is one of the features that only class components can do. You literally cannot do these in function components so if you need something that has error boundaries, you must use class components. That's just one thing to keep in mind. I'm just emphasizing that because sometime in the future you're gonna wonder why doesn't this work and this is why.
[00:00:18] We're gonna go implement a lifecycle method called component did catch. This is really useful if you expect errors coming from within your application. So a good example of this is what happens if I try and go to details slash that. Undefined, undefined, undefined it's just kind of like doesn't work super well.
[00:00:43] And we get a bunch of errors, right? Or green or something like that, it just doesn't really know what to do with itself. So this is something that you can actually like handle with, What's called an error boundary. I can say, hey, if there's an error somewhere in here, don't crash my application.
[00:01:04] Just go ahead and catch it and then do something with it. So something I've seen apps do is I'll put one error boundary at the very top level. So they're like, hey, if an error happens anywhere in here, let's recover, let's send the user back to a good state.
[00:01:17] Let's not just crash the application altogether. So let's go ahead and go do that. We're gonna make a component at the top level called ErrorBoundary, ErrorBoundary.js. I actually find these really useful with APIs, especially if that API is unreliable. I don't know if you've ever had an unreliable API before.
[00:01:47] If so, I'm sorry, my apologies. Might have been my fault, I don't know. But this will help you if sometimes they come back with incomplete data or sometimes a 500 or anything like that. So first of all, I'm gonna say I mostly took this from the React docs.
[00:02:04] So as in copy pasted, so that's why I'm going to go ahead and just give them a shout out there. Import component from react and we're gonna import link from react-router-dom. I wanna say class ErrorBoundary extends, Component. Here we're gonna say state=hasError. And it's gonna be false cuz by default, it doesn't.
[00:02:48] And then we're gonna have to create a function called staticGetDerivedStateFromError. It's a mouthful, I know. And then here we're gonna say return hasError true. So here you can actually I think you can get at the error object, if I take a look at this, might not say, component.
[00:03:20] You might actually be able to get at the error and see what caused the error. And you can do different things based on the error. If you get an API error, go here, if you get a syntax error, go somewhere else. I don't really care I'm just gonna ignore and say like, hey, if you encounter an error, just say that you have an error.
[00:03:40] And actually probably something good to do is actually here in componentDidCatch. Here gonna get the error and the info about the error. Here I would log this to Sentry or Azure Monitor or New Relic, TrackJS, there's a million of these error monitoring services. This is where I would call that, I would call out to that it's like hey users are hitting an error here, do something about that.
[00:04:17] Here I'm just gonna say console.error, the oldest school of error monitoring is your console. And you're just gonna say errorBoundary. Caught an error. Error info. Then here I want to say underneath that render, If this.state.hasError, then return, Whatever you wanna say, right? This listing has an error and then we can throw a link in here, a link to, Click here to go back to the home page.
[00:05:23] So if it has an error render goes we're super sorry, click here to go back to the homepage. Or we can say return this.props.children. So this is what we were talking about before. There's key and another one of those reserved props name is children. And the reason for that is if I can do something like this errorBoundary.
[00:06:00] So this, whatever I pass inside of errorBoundary, this is children, right? This is what gets passed in the children. So what I'm saying here is if I have some sort of error, do something about it, right, render this. If I don't have an error, just render whatever is in the middle of this, right?
[00:06:16] So basically, be invisible if I don't have an error. Only show up when I have an error, does that makes sense, all right? Down here at the bottom, there is export default, errorBoundary. So let's go into, Details. So we're gonna put this inside of details, so if there's ever an error inside of details, we wanna do something about it.
[00:07:02] So we're gonna say import ErrorBoundary from ./ErrorBoundary. Now, there's a peculiar thing about it. What you're tempted to do is, okay, I'm just gonna put ErrorBoundary here, right? How would a JavaScript error work though? If I had an error here, let's just say I have throw newError. Right, it would never hit here, right?
[00:07:38] It would stop there and it would go up. So actually the ErrorBoundary has to exist above it in a new component above it. So I can't just drop it in here. It'll only catch things in components underneath it. We have to have a component above it that does it.
[00:07:51] So an easy way to do that, Is we would do it here. So we already have a higher order component. This is kinda where you start getting into weird things where we have multiple nested higher order components. Cuz that's exactly what we just did with error boundary. It's a component that adds functionality but doesn't add display, that's a higher order component.
[00:08:14] Which is just a fancy name for things that don't display. So what I'm gonna do is I'm gonna say const details withRouter = wihtRouter(Details). Then underneath that, I'm gonna export default function details with router with, or whatever you want to do. We'll just call it WithErrorBoundary. I want to say return ErrorBoundary details with router.
[00:09:13] Now, could we have put this in here or something like that? Yeah, sure, I mean, in theory now if there was ever something wrong with router, we could actually catch it here. But if there's something wrong with router, you're gonna have bigger problems than just an error boundary.
[00:09:27] So it doesn't really matter either way. So I say, however you choose to export these works for me. But now we have an error boundary here with details, actually, so we have an error in here, I'm just gonna leave that. Because let's see what happens when there's an error inside of our component.
[00:09:44] I'm gonna save. I'm gonna come over here, but I'd make this an h1. My CSS strikes again, which is to say poorly written CSS strikes again. Make that an h2 and now you'll see this listing has an error click here to go back to the homepage. I was trying no write no CSS and got a little too clever.
[00:10:06] Story of my life, really, if we're being honest. So now I can click here, I can go back, chills, no problem, right? So let's go back here to details, let's go back here, delete that. Refresh the page, go back to the Luna page. And now it's just totally transparent, right?
[00:10:28] So now we can just be assured that even if there's some problem with one of these components. No problem at all, it'll work just fine. So this is actually still gonna try and render this out. I think we were too defensive about this. So let's say for a second, we did this and like heroes came back undefined, in fact, this actually might just do it but, Cuz we did the default props, that's still gonna work.
[00:10:57] Anyway, we were too defensive of our code, so it's not going to throw any errors. I'm not gonna apologize for that [LAUGH]. But if there's ever an error that came back from the API, or maybe the API stopped responding, right? That would be one place that would do it.
[00:11:12] But now we can be assured that it's never going to just crash on the user. It's never just going to show them not rendered, which is what we don't wanna see. We wanna see it show them something and allow them to gracefully recover from an error.