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

Building a React.js App: Transitions with 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 video, we’ll walk through how to use React Router to transition from one Route to another while passing that new Route data via route parameters.

As of right now, our menu we've been creating is just a bootstrap menu with a text menu. But what we actually want to have happen is we, as we've been doing, want to be able to enter a username, and when I click Search GitHub it goes and it transitions to this new route, passing along the username that we typed in. That's what we're going to do in this video.

Let's go ahead and go back to our code, and let's go ahead and make a new file inside of our components folder called Search GitHub.js.

The very first thing, we're going to require React. Then what we're going to do is we're going to require the router, because we're going to rely on the router to actually do the transition for us between our routes, so require React router. Then, as always, we make a component using React.create class. Then we export this component.

The mixins we're going to use for the transition is the history property on the router object. Then let's do a render function, which returns, it's going to return a form, so we're just going to have to bootstrap stuff here.

This form is, whenever it gets submitted, is going to run this.handle submit, which we'll create in a second. Then from here, we're going to have two divs, one is going to be the input field, which is going to be of type text and a class name of Form Control. Then as we talked about in the last video, as a ref equal to this.get ref, which is going to call this function.

Then what we'll do is we'll have this input ref and let's go ahead and say this.username ref equals ref.

The next container is going to be our button. Whoa. This button is going to be of type submit, have a class name of BTM, BTM block, and we'll say BTM primary for the color and have a text of Search GitHub, and then we're going to close our button.

Now, what we need to do is we need to make a function called Handle Submit, that will get the value of our username ref and transition us to our profile route, passing along that username that we're getting from the ref.

Inside here, let's go ahead and create a Handle Submit method. As usual, let's go ahead and get the username, just as we did before. That's going to get us the username of this input field, or the value of the input field. Then let's go ahead and reset that to an empty string.

Then, this is kind of where the magic happens.

Again, because we're using a mixin, what React is doing is it's taking any properties on the React [inaudible 4:00] modular object, and t's adding it to our instance. One of those properties is called History, which has a property called Push State.

What we can do is Push State allows us to transition to a new route. We, the route we want to transition to is profile/plus whatever this username is. Because if you'll remember a few videos ago in our routes config, we said, hey, whenever someone goes to profile/whatever username, go ahead and render this profile component.

What we're doing here is we're saying, hey, whenever someone clicks on this Handle Submit button, go ahead and grab the username and then go ahead and take them to this profile/whatever that username route is.

The last thing to do is, let's head over to our main component. Instead of menu here, we are going to render our Search GitHub component, which we need to require.

Let's say Search GitHub equals, and we're in the same directory, so let's just get Search GitHub, and now let's check to see if this is working.

We head over here, we can search for a username and it should redirect us to /profile/this username. Then our notes component renders, let's give this another test, and there we go.

Philip Cox
Philip Cox
~ 9 years ago

Hello. Nice tutorials, thanks Tyler. I believe getDOMNode() is deprecated and replaced with findDOMNode(). Just thought I'd let folks know :)

Tyler McGinnis
Tyler McGinnisinstructor
~ 9 years ago

Thanks Philip! Dang breaking changes.

~ 9 years ago

Hi Tyler, thanks for the great lessons!

I'm having some issues with routing transitions (lesson no. 8). The js console output this error message when I focus on the search box in the top navigation bar (the SearchGithub component):

Warning: No route matches path "/profile/". Make sure you have <Route path="/profile/"> somewhere in your routes

I've tried to edit the routes.js files to get something like the following, but it doesn't solve the problem:

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

If I manually change the URL to /profile/anyusername the Profile component is rendered properly, so I guess the problem is with the transition.

Do you have any idea?

Alex
Alex
~ 8 years ago

Getting - this.transitionTo is not a function

Mihnea Ciobanu
Mihnea Ciobanu
~ 8 years ago

I'm getting the same error.

egghead eggo
egghead eggo
~ 8 years ago

The lesson video has been updated!

Zach  Sosana
Zach Sosana
~ 8 years ago

two questions:

First one is how do we get the enter event key to work automatically when we use the search bar in our main component to work right off the bat, but when we use the submit button on notes the enter button doesn't work, how would we implement this so when the user hits enter on his keyboard it triggers submit? and how come it just worked with our search submit ?

second questions is related to lesson 8 transition, once we hit submit and on the profile page, the search no longer works if we are on /profile/whateveruser, instead it adds another profile/whateveruser in addition to our current url, ex url /profile/whateveruser/profile/whateveruser, how do we update that so when we are on a certain profile we can still use the search box?

Jeremy Zilar
Jeremy Zilar
~ 8 years ago

Question about capitalization: Why do you capitalize your filenames and folder names?

Tyler McGinnis
Tyler McGinnisinstructor
~ 8 years ago

Just convention. I capitalize components and hence capitalize the file they go in.

Tom Warhurst
Tom Warhurst
~ 8 years ago

I keep getting "Uncaught TypeError: Cannot read property 'value' of undefined", does anyone know what's wrong?

Tyler McGinnis
Tyler McGinnisinstructor
~ 8 years ago

Have you checked your code against the solution branch? (https://github.com/tylermcginnis/github-notetaker-egghead/tree/08-transition) Also make sure all your versions match as well.

Jin
Jin
~ 8 years ago

Router.History mixin has deprecated, wonder what;s the best way to do it now, push to browserhistory or conext router?

Tyler McGinnis
Tyler McGinnisinstructor
~ 8 years ago

You can check out the changelog between React Router 1.0 and 2.0 here

Jason McIver
Jason McIver
~ 8 years ago

using 2.0.1 context router worked for me https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#navigating-inside-deeply-nested-components

Sergei
Sergei
~ 8 years ago

For those that are doing this example on the latest version of react-router (2.0.x) which breaks this example, and apparently Mixins are officially deprecated (You get either error: [react-router] Router no longer defaults the history prop to hash history. Please use the hashHistory singleton instead. or [react-router] the History mixin is deprecated, please access context.router with your own contextTypes), I fixed this with in 2 ways:

Change app.js's render content to <Router history={hashHistory}>{routes}</Router>, and instead of using a mixing to navigate on SearchGithub.js , do:

var History = require('react-router').hashHistory;
{...}
History.pushState(...)

I really wish Tyler gave his opinion on this and the right way to do this on react-router 2.0.x. I think you can also do this with Contexts (but I haven't reached that point yet and this was the easiest solution at the time). Feel free to read more about this here: https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md#hashhistory

Satyajeet Parida
Satyajeet Parida
~ 8 years ago

I tried the example. It says 'Cannot read property 'isRequired' of undefined'. Router.PropTypes doesn't have a 'router'.

marlonjfrausto
marlonjfrausto
~ 8 years ago

I just ran into these issues and I wanted to thank you for hinting at a solution Sergei ! I ended up implementing a slightly different solution, hope this helps others save some time debugging.

-changes to your App.js file

import { hashHistory } from 'react-router'

ReactDOM.render(
<Router history={ hashHistory }>{routes}</Router>,
document.getElementById('app')
)

changes to your SearchGithub.js file (import statement goes along with your require statements): ... import { hashHistory } from 'react-router'; ... hashHistory.pushState(null, "profile/" + username) ...

Max Orelus
Max Orelus
~ 8 years ago

This worked for me.

Jonny Adshead
Jonny Adshead
~ 8 years ago

Nice marlonjfrausto, I found this really helpful for getting a few more bits of detail. https://github.com/reactjs/react-router-tutorial/tree/master/lessons/12-navigating

Mateusz Szymański
Mateusz Szymański
~ 8 years ago

My handleSubmit function that works nice with React-router@2.8.1

e.preventDefault() will stop page from full reload that happened on chromium.

handleSubmit(e) {
    e.preventDefault();
    const username = this.usernameRef.value;
    this.usernameRef.value = '';
    Router.browserHistory.push(`/profile/${username}`);
  }
Steven
Steven
~ 8 years ago

Jason Do you need to make any changes to App.js to get this to work? I don't follow why this.context.router is defined in the component scope, can you please help me understand? Also is it possible to use <Link to = "" /> and if so what is best practice (and why?)? Thanks!

Alexius Hale-Dubuque
Alexius Hale-Dubuque
~ 7 years ago

I'm seeing this error (Uncaught TypeError: Cannot read property 'pushState' of undefined) with the following line of code in SearchGithub.js: "this.props.history.pushState(null, "profile/" + username).

Was there a solution given to this. My code is exactly like the solution code in github.

Alexius Hale-Dubuque
Alexius Hale-Dubuque
~ 7 years ago

WOW, just like that I solved my issue. In SearchGithub.js: Replace: "this.props.history.pushState(null, "profile/" + username)" with this: "hashHistory.push(/profile/${username})"

Liza
Liza
~ 7 years ago

Thank you! This fixed my problem :)

Markdown supported.
Become a member to join the discussionEnroll Today