Check out a free preview of the full Complete Intro to React v2 (feat. Router v4 and Redux) course:
The "Async Routing" Lesson is part of the full, Complete Intro to React v2 (feat. Router v4 and Redux) course featured in this preview video. Here's what you'd learn in this lesson:

An AsyncRoute is a higher-order component that will display a loading state until a component is completely loaded. Once the targeted component is loaded, the AsyncRoute will remove the loading state and display they component. Asynchronous loading happens through the use of the System.import() method.

Get Unlimited Access Now

Transcript from the "Async Routing" Lesson

[00:00:00]
>> Brian Holt: We're gonna go create our own higher order component now. Cuz what we eventually want to do is here inside of app.js, we have this matches. But really what we want to do here is we wanna have this AsyncRoutes that instead loading details right away right upfront. We wanna tell it, don't load details until you need to.

[00:00:29] That's what we wanna tell it. So the first thing we're gonna do is we're gonna create a new component. And it's gonna be call AsyncRoute.js and what this is gonna do, is it's basically going to allow us to show a loading state until we have the component loaded.

[00:00:47] And then, we're gonna show the component. So this is a higher-order component, right? This component doesn't actually display anything of it's own, it just encapsulates behavior. So, we're gonna import React from react.
>> Brian Holt: From 'react' const object = React.Proptypes.
>> Brian Holt: And we're gonna say const AsyncRoute = React.createClass.

[00:01:30]
>> Brian Holt: propTypes.
>> Brian Holt: Props are gonna be an object of some description and then loading promise will be another object. There probably is a proptype validation out there that is a promise one, but I don't care so this is fine. It's going to be a get initial state. So, when very first load this component, it's going to return loaded false.

[00:02:09] Right, because we're going to be using this for asynchronously loading routes. Then compinentDidMount. So what's gonna happen is this acing crout is going to be passed a promise right. The result of this promise is the component we can use right. But we can't use it on the first try, so we have to wait until it's finished loading.

[00:02:37] We're going to know when it's done loading based on the promise that it's given us. So we're going to say this.props.loadingPromise.then((module)).
>> Brian Holt: So when this, when then fires, it's going to hand us module and we're going to be able to use module at that point.
>> Brian Holt: So what we're gonna do is we're gonna say this.component=module.

[00:03:12] So we're gonna store it on AsyncRoute. Notice we're not gonna stick this on state. We're not gonna put in state. Because this isn't mutable after we load it the first time, right? We're not gonna keep changing this, right? Once it's loaded, it's loaded, it's done. We don't have to worry about it, okay.

[00:03:33] Once we do that, then we're gonna say this.setState({loaded: false}). The other thing is that, if we stick it on State that means, every time that it goes to re-render, it's gonna check the entire module, which might be very big, right? And we don't wanna do that. We only want it to have a fast re-render.

[00:03:55] So we're only going to stick render on there instead of the component. Does that make sense, okay?
>> Brian Holt: So that's what component and mount's gonna do. Then on render.
>> Brian Holt: What we're gonna do down here is we're gonna say, if (this.state.loaded), then we're going to return this.component_this.component_this., sorry,...

[00:04:29] this.props.props.
>> Brian Holt: Okay? So if we have loaded the module successfully, we're gonna instantiate this.component. So because we have a period in here, it knows, okay, this is a java script object, right? Or a component we created ourselves. And then it's going to say, I'm going to pass in those props that I get back.

[00:05:04] Yeah?
>> Speaker 2: On line 17, should it be true?
>> Brian Holt: Yes, thank you.
>> Brian Holt: Otherwise it's gonna return some sort of loading state. So I'm just gonna give it like a really dumb, just like it's gonna say loading in an h1. Be might have some fancy spinner here and that will be fine.

[00:05:30]
>> Brian Holt: So does this make sense so far? If it's loaded, it shows the component. If not, it shows a loading state. That's all this does. And here we're just passing in whatever props the async route got as props. And we just pass those on to whatever the component was.

[00:05:46] Because we don't want AsyncRoute to actually care, we want it to be very flexible. We want to be able to use this on any route, not just one route. So now we have this AsyncRoute. Let's go plug it in and see if that all makes sense as we plug it in together.

[00:06:06]
>> Brian Holt: So let's just go do one of them. I'm gonna do landing real quick. So go to ClientApp.Js, sorry not ClientApp, but App.Js.
>> Brian Holt: And we're going to not import landing. We going to stop importing that. And we're going to import AsyncRoute from./AsyncRoute.
>> Brian Holt: Okay, to make it so that node doesn't fail on this.

[00:06:55] I'm just gonna say, if (global) so this is a dirty way to check if you're a node or not. I don't suggest doing this in production but this is going to work for our case. Globals like the window of node. global.System = { import }.
>> Brian Holt: We're just basically just kind of quote, unquote poly filling.

[00:07:26] There's a better, we're not poly filling cuz we're not making this work, we're just saying don't fail when this function's called.
>> Brian Holt: And then what we're gonna do here on landing. So we have this one right here. I'm gonna put this one on multiple lines.
>> Brian Holt: So we're gonna abuse this trick that we had to have down here.

[00:07:54] We're gonna say props, AsyncRoute props=props. So we're just passing in whatever this got into AsyncRoute. And then we're gonna say
>> Brian Holt: component
>> Brian Holt: No I called this not component, it's loadingPromise. loadingPromise=System.import. ./Landing
>> Speaker 2: I think you need a scrolling brace on a different place. Doesn't the loadingPromise go with the AsyncRoute?

[00:08:53]
>> Brian Holt: Yeah, it does.
>> Brian Holt: Yep, okay.
>> Brian Holt: And then that needs to be closed as well, right.
>> Brian Holt: Okay, so let's unpack what's happening here, okay. This is just like one of those, literally a statement functional component that's generating an AsyncRoute. We're passing whatever props we're getting from Match into AsyncRoute and loadingPromise right here.

[00:09:44] We're doing a system.import. So System.import is the new way of doing asynchronous module loading. If you ever used require.ensure before, that was the old way of doing it. System.import is the new way of doing it. And we're saying, hey, asynchronously load ./Landing. This generates a promise, whenever that promise is fulfilled, that's when it gives you that module.

[00:10:12] Okay we're passing that to AsyncRoute, which is either going to display it if that promise has resolved. And until then it shows a loading state.
>> Brian Holt: Now that's all we have to do. At this point webpack is smart enough to say, okay, I'm not gonna load landing right away.

[00:10:32] I'm gonna wait until landing is requested and then I'm actually gonna go to the server and grab it. And it's smart up to say like, okay landing is this big dependency graph over here. I'm just gonna cut if off right there. So, like for example, if I only require axios inside of Landing, it's also not gonna include axios until I request Landing.

[00:10:54] So, it's gonna be smart enough to cut off that entire part of the dependency graph. So this can actually be a pretty substantial savings, yeah.
>> Speaker 2: Richard is asking if that component line 20 should get GetComponent() instead?
>> Brian Holt: Should be GetComponent()?
>> Brian Holt: I'm not sure what he's talking about.

[00:11:27] GetComponent. That's the old react router way of doing it. React router has no opinion on doing asynchronous loading. No, it has no helpers. You're on your own. Yeah, so that's the old React router way of handling asynchronous stuff. But thanks to this new way of doing it, they don't have to worry at all about it.

[00:11:47] And it's totally on us to figure it out.