⚠️ This lesson is retired and might contain outdated information.

Building a React.js App: componentWillReceiveProps and React Router

Tyler McGinnis
InstructorTyler McGinnis
Share this video with your friends

Social Share Links

Send Tweet
Published 9 years ago
Updated 6 years ago

In this lesson, we’ll learn how React Router uses the componentWillReceiveProps life cycle method in order to give you any route changes that occurs in your application. We’ll leverage this to fetch new data about different users when the user requests that data.

One thing you may have noticed as you were playing around with this is, every time we go to a new route, we're refreshing the whole view. If I go to another user, it refreshes the view. That's obviously not what we want, because we're building a single-page application and we don't want the whole view to refresh.

That's because we have a typo or a bug in one of our previous videos. Go ahead and go to the search GitHub component. Right here, instead of being a profile/slash, we want it to be /profile, and then the username. Once we do that, then we should get something like this. I'm going to go home, I'll type in a new username, and there we go.

You'll notice here, if I type in a new username now, it doesn't refresh the whole view. This data is still the same, even though we're going to a new route. The reason for that is because we're receiving new props into our components, but we're not doing anything with those props. React gives us another handy little lifecycle method that we could hook into, which is called componentWillReceiveProps.

What this does is, whenever our profile component receives new props, this callback function is going to get invoked. What's nice is, whenever react-router changes routes, because our routing is going through props, this function will get invoked, and then we'll have those new props.

Let's go ahead and see this. What I'm going to do is, inside of componentWillReceiveProps, let's just console.log. The nextProps are with the nextProps. What we should see here is, if I refresh this and go to a new username, we get these new props and, under params, we have the username.

Let's go ahead and change up our component a little bit. What I'm going to do is let's go ahead and make an init function. What's going to happen is we're going to call this data or this chunk of code when the component mounts, but also we want to set up a listener to the new user whenever we receive new props.

Let's go ahead and I'm going to copy this code and put it into my init function. Then, in componentThenMount, I'm gong to call this.init. We don't want to query this.props.params.username, because what's going to happen is, when this init function runs, if we call it in componentWillRecieveProps, we're not giving it the new props.

If I'm on my own profile, TylerMcGinnis, if we type in a new user, this.props.params.username is still going to be TylerMcGinnis. What we want to do is let's go ahead and have this init function take in a username, and then we'll switch out all of these for that username.

Then what we can do is, whenever the component receives props, we're going to go ahead and pass this.init.nextProps.params.username. Also, when our component mounts, we're still going to pass it this.props.params.username. Init is now taking in the username, whether it's from the params itself or, when we recieve new props, those next props coming in.

Let's go ahead and see if this works. Everything looks good. Webpack is running. Hit refresh. Let's go to Spencer's profile. This.state.notes is already bound to a Firebase reference.

The reason this is being thrown is because, in our component didMounts, we run init, and that comes in here and binds to our notes property on our state. Firebase isn't going to let us bind to multiple things, which make sense.

What we're going to do is, inside of componentReceivesProps, before we call init again, let's go ahead and call this.unbind notes. Now when we receive props, we're going to unbind what we bound to in our component when it mounted, and then we're going to rebind to the new username.

Let's see if this works now. TylerMcGinnis, there we go. Our data loads, and we can go to any username we want here.

egghead eggo
egghead eggo
~ 8 years ago

The lesson video has been updated!

Alan Eng
Alan Eng
~ 8 years ago

Can you explain what the role of componentWillUnmount is in this app? I commented it out and was able to have the app function perfectly without it. Maybe it's because the component never unmounts? I'm not sure in what situation a component would unmount or even how to unmount one.

Tyler McGinnis
Tyler McGinnisinstructor
~ 8 years ago

Great observation! Usually the role of componentWillUnmount is to remove/clean up any listeners you've established whether that's with flux, Firebase as in our example, or any other listeners. If you take out componentWillUnmount, you'll no longer be removing the listener to Firebase. Now, this isn't a HUGE deal, but what if that component mounts again, then you've created another listener. Now all of a sudden you have two listeners to firebase. And if this happens again, 3 listeners etc etc. So componentWillUnmount is mostly used to remove listeners (therefor protecting against memory links etc)

Jin
Jin
~ 8 years ago

I have been following this tut this far, thank you Tyler for your hard work. Correct me if i am wrong, since the Rounter History has deprecated, i am using context router to replace it, and the search function is ok and you dont need the componentWillReceiveProps to unbind and rebind incoming props to render the new page?

Kylan Hurt
Kylan Hurt
~ 7 years ago

For some reason when I try to access jakelingwall's profile I get the following error in my console: bundle.js:1178 Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {text}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of NotesList.

Otherwise the lesson and code seems to work fine.

Andrewsh86
Andrewsh86
~ 7 years ago

There seems to be a bug after introducing the change of "profile/" to "/profile/" in SearchGithub.js.

After completing all of the code in this lesson, when you search for two users, they'll show up and load fine, but the third one will come back as an undefined user and the url will be something like this:

<path_to_project>/public/index.html?#/profile/undefined?_k=kb9dpq

I tried searching andrewsh86, then tenderlove, then SamyPesse

If I replace the "undefined" in the url with the correct username, it works fine. There's something buggy happening with the SearchGithub.js and not pushing to the history correctly. I verified that changing it back to be "profile/" fixes this problem, but reintroduces the issue of loading the page completely again.

Markdown supported.
Become a member to join the discussionEnroll Today