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

Building a React.js App: State, Props, and Thinking in React

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 video, we’ll build out the skeleton of our main React.js components. We’ll talk about how to think in terms of components as well as learn about state and props.

As we talked about a few videos ago, the biggest component in our application is going to be this profile component we'll make, because that's what's going to manage the state for this user profile component, the repos component right here, and also the notes component. Let's go ahead in this video, let's make this profile component, and then let's just make these three child components.

Let's go ahead and head over to our components folder. Let's make a new file called profile.js. Very first thing we're going to do, as always, is require React. We're going to need React router later on, so let's just require it right now. That should be good for now.

Let's go ahead and make a new profile variable and set it equal to React.createclass to create our component. Then, let's go ahead and set the render method. This render method is going to return. Let's go ahead and make sure that we export this component.

Looking back at our application that's finished, you'll notice that this is the component we're building right now, the profile component. This component is going to be managing three different states really. It's going to be managing the user's profile data, the user's repo data, and this notes data.

Let's come in our component. We're going to add a get initial state method on this component. What get initial state does is it's going to set the initial state of the component, meaning anything that this component is going to handle, any state that this component is going to handle, you're going to basically initialize that state right now.

You usually just initialize it with empty data. We're going to return notes, which is going to be an array, bio, which is going to be an object, and repos, which is going to be another array. Eventually, these are going to get populated. These data sets are going to be passed down to these children components, which they'll then render.

Let's go ahead and add this new profile component to our routes. Now let's head over to routes.js. The very first thing we're going to do is require our new profile component that we made, component/profile. Now what we want to do is we want to be able to hook up our profile component to our router.

Down here, we're going to say route. We're going to specify a new route. So whenever someone goes to our app/profile/some username, this route is going to be active. The component that's going to be activated is this profile component.

Let's go ahead and verify that this is all hooked up now. When we go to our app/profile/any name, what we should see is our profile component, which should give us just this static text. Web pack is still running. If we hit refresh and then go to /profile/anything, here we go. We got our static text.

You might have seen this little gross hash up here. You can get rid of that. I'm not going to worry about it in this video, but if you want to get rid of it, go ahead and look into React router's create hash history.

The reason I'm not going to do it in this video is because you have to have a server. We're obviously serving these just going to the path itself. So we're not going to do it. But you can get rid of these using React router. Don't worry too much about those.

Everything seems to be working, but what we still haven't done is we still haven't figured out a way to get the username that we pass in through the URL into our profile container. A very fundamental principle of React is this idea of passing props down to a component.

You'll notice here that our profile component has this state, but what if we were rendering another child component? Let's say we had a component called Display repos because we'll eventually have something like that.

The way we want to get these repositories down to this component is something like this. We could say, "Repos = this DOS state.repos." I'm going to call this child repos just so you can see the difference.

What we're doing is we're saying, "Hey, display repos. You're going to receive this DOS state.repos as child repos." Now if we were to go inside of this display repos component, the way we would access child repos is by querying this.props.child repos.

Through props, we're able to gain access to data that's stored in our parents or stored in any other higher component. The reason I tell you this is because this is kind of how React router works.

Right now, everything's good, and our profile's working, but we actually haven't figured out a way to query our username yet. What we're going to do is let's just console that log this.props. Let's take a look at that.

If I'm here, here's our props objects. This is everything that's being passed to the profile component. You'll notice that one of these is called params. This has a username property which is Jake. If I change this, then params has a username property which is Tyler McGuinness.

The way you access route parameters with React router is the same way you access any data that's being passed down to a child component, it's through this.props. Let's just display that to the page right here. Stop props.params.username. Again, the reason it's called the username is because that's what we specified inside of our routes.

When I load this, we should see user profile component and then the name of the route param. I changed this. It updates it.

One thing I didn't mention was the way you display variables inside of JSX is just with this single curly brace.

Go ahead and make some more components in your components folder. Go ahead and make a GitHub folder. Also, make a notes folder. In the GitHub folder, make two files. The first file is going to be called repos.js. The second file will be called userprofile.js.

In the notes folder, let's go ahead and make a file called notes.js. What these three files are going to be are the component definitions for each of our three components, our user profile component, our user repos component, and our notes component.

Let's go ahead inside of repos. We're going to require React. Then we'll make a new component using React.createclass. We'll have it just render something simple. It's going to render repos. Because this is going to very similar to the other ones as well, let's just copy and paste. We have user profiles. This is user profile, and then notes is going to be notes. I'm going to change this to notes.

Now let's head over to our profile component and use each of these components we just made. The very first thing we're going to do is let's require all of these to repos is going to be require. We need to go into GitHub and then repos and then user profile. It's going to be the same thing. It's in the GitHub folder. Then our notes component is inside the notes folder.

Now in order to use this, you saw this a little bit earlier, but what we're going to do is simply say user profile. It's self-closing. Then, here, instead of repos, we have our repos component. Here instead of notes. we have our notes component.

Let's see if this works. There we go. This is good.

But you'll notice here we have user profile, repos, and notes. We also have repos, bio, and notes. What we want to do is we don't just want to render these components. We actually want to pass data down to them so that data can be rendered inside of these child components.

User profile, what we're give it first is a username. If you'll remember earlier, we can access the username of a route parameter by doing this.props.params and then whatever that route param is called. In this case, it's called usernames.

But we also want to the bio which is currently living on our state. Same thing with repos. We're going to pass it down repos as this.state.repos. Then notes, this.state.notes. Now let's go ahead and go into user profile. Let's just render the props that it's getting. Let's return one big div just so we can verify we're getting stuff. We'll say, "User profile."

Then here let's do the stop props.username. Here, let's do bio as this.props.bio.name because, let's go back to our profile, now let's initialize bio just with some default name. Now if we go, our user profile renders Jake or whatever the route param is. Then we also get bio.

Just real quick, I'm going to go ahead and inside repos let's just show that's we're at repos. The repos are the stop props.repos. Same thing for notes. We're on notes. Let's render the stop props.notes.

Let's see if this works. There we go. Let's go ahead and initialize notes with 1, 2, 3, and repos with a, b, c. We're up.

Marcelo
Marcelo
~ 9 years ago

What you did to change the color of your browser console ?

Marcelo
Marcelo
~ 9 years ago

Why am I getting this error in the console: Uncaught TypeError: this.getParams is not a function

Tyler McGinnis
Tyler McGinnisinstructor
~ 9 years ago

https://chrome.google.com/webstore/detail/brogrammer-dev-tools-them/alolpfkmcjdkieibielpffiehpobafae

xmen4u
xmen4u
~ 9 years ago

In Profile.js , it should be "bio={this.state.bio.name}/>" , instead of "bio={this.state.bio}/>". Without this, React yells a warning:

"Warning: Any use of a keyed object should be wrapped in React.addons.createFragment(object) before being passed as a child." and it's right! as it doesn't know what to property from Object / Array to print

Tyler McGinnis
Tyler McGinnisinstructor
~ 9 years ago

I commented on this in the video. We'll fix it in a future video. We only do it to show the data is there initially.

Jason
Jason
~ 8 years ago

Why am I getting this error in the console: Uncaught TypeError: this.getParams is not a function

Use this.props.params.username if using react-router 1.0.0-rc1

egghead eggo
egghead eggo
~ 8 years ago

The lesson video has been updated!

Mark
Mark
~ 8 years ago

I'm stuck with when trying to load the profile (video 3:15), results in the console error: bundle.js:829 Warning: [react-router] Location "//profile/blah" did not match any routes

The completed github code seems to run fine, but the syntax is completely different, and it's the completed code, making it very difficult / impossible to figure out why my uncompleted code isn't running.

Tyler McGinnis
Tyler McGinnisinstructor
~ 8 years ago

Have you checked the specific branch for this video? https://github.com/tylermcginnis/github-notetaker-egghead/tree/03-react-router Might be easier to compare to yours rather than the final version.

Aline Bastos
Aline Bastos
~ 8 years ago

Mark, did you resolved this issue? I'm getting the same error..

Harini Janakiraman
Harini Janakiraman
~ 8 years ago

Mark & Aline, I figured out that it works if you have "//" added to your react-route, like below

<Route path="//profile/:username" component={Profile} />

Carmen
Carmen
~ 8 years ago

I had the same error. Your solution worked well however, I don't quite understand why. Any ideas?

I just started this course so I'm using the latest as today. I'm using "react-router": "^2.4.1" Thanks

Sebastian Belmar
Sebastian Belmar
~ 8 years ago

when you are typing "/profile/whatever", notice your have a hashed string after "index.html#/" before "/profile/whatever", it looks something like this "index.html#/?sf_31dsfds/profile/whatever", that hashed string in the middle now does not represent anything, so the browser is looking for a url called "index.html#//profile/whatever" but you don't have it, that's why you are getting this error. So when you testing route, delete the hashed part.

Owen
Owen
~ 8 years ago

Hi, I recently started this series and am using the most-recent react router 2.6.1. I have been stuck for some time with a similar error "Warning: [react-router] Location "/Users/owen/Dev/github-notetaker/public/index.html#/profile/someone" did not match any routes. I have tried all the suggested solutions but am stuck now. I have changes my routes.js file to :

var Main = require('../components/Main');
var Home = require('../components/Home');
var Profile = require('../components/Profile');
var Router = require('react-router');
var Route = Router.Route;
var IndexRoute = Router.IndexRoute;

module.exports = (
    <Route path="/" component={Main}>
        <Route path="//profile/:username" component={Profile}/>
        <IndexRoute component={Home}/>
    </Route>
);```

I am still getting 'Warning: [react-router] Location "/Users/owen/Dev/github-notetaker/public/index.html#/profile/someone" did not match any routes'   though and don't know what else to try.  Any idea what is wrong here ? 
Steven
Steven
~ 7 years ago

At 41 seconds you require "react-router" and say we'll need it later? Maybe I'm missing something obvious but where later is this actually required? Do we need this line at all? Thanks for the great series!

Markdown supported.
Become a member to join the discussionEnroll Today