Routing in React
By: Nicky Liu
Tags: Reactrouterv4, React

I will go over how to set up routing in react!

React routing works by manipulating your window. If you open up the console and type “window.history” you get back something like:

History {length: 4, scrollRestoration: "auto", state: null}

You can change the state by doing:

window.history.pushState({newState: "This is a new state!"}, "new state", "new-state")

If you type “window.history” again you will see that the result has changed. You set the state to the object {newState: “This is a new state!”}, and you will see at the end of the url there is now a “new-state” added to it.

If you now type “window.history.back()” the url will be changed to the earlier form, and if you type “window.history” the state will have changed back as well. If you enter “window.history.back()” again you will go back an entire page. ReactRouter is the way to manually manipulate the url and state through this method

Now let’s first set up a new react app.

create-react-app (route-testing)

Next get the server up and running.

npm start

Now install react-router-dom.

npm install react-router-dom

Import the “BrowserRouter” component as

Router” and also import the “Route” component into “index.js.”. Also add a function and have the path render that instead.

import React from 'react';

import ReactDOM from 'react-dom';

import './index.css';

import App from './App';

import * as serviceWorker from './serviceWorker';

import {BrowserRouter as Router, Route} from 'react-router-dom' const Test = () => {

return (

<div>

Test

</div>

)

} ReactDOM.render((

<Router>

<Route path="/" render={Test} />

</Router>),

document.getElementById('root')

); serviceWorker.unregister();

Now you will see the contents of the Test function. We gave the page a path in which it renders Test, and since we are currently on that path it renders properly.

If you go to your browser bar and add random letters after the /, it will still work at the moment. That is because we called it just “path”, which renders everything to that path as a default. If we wanted it to only render something when the exact words are used, we use “exact path”. If you change the line to:

<Route exact path="/" render={Test} />

You’ll notice that it no longer works when we have the random characters after it, but if we delete them and change it back to just / it will once again display properly.

Let’s add some other routes and functions.

const One = () => {

return (

<div>

ONE

</div>

)

} const Punch = () => {

return (

<div>

Punch

</div>

)

} ReactDOM.render((

<Router>

<Route exact path="/" render={Test} />

<Route exact path="/one" render={One} />

<Route exact path="/punch" render={Punch} />

</Router>),

document.getElementById('root')

);

If you type in /one in the url now it will show the word ONE under test. If you instead replace it with punch it will show the word punch under test.

Now lets add some separate components and add those routes for them now.

Create two files, “Hi.js” and “Bye.js”.

Enter the following code inside of hi:

import React from 'react'; function Hi() {

return (

<div>

Hi

</div>

);

} export default Hi;

and the following inside of bye:

import React from 'react'; function Bye() {

return (

<div>

Bye

</div>

);

} export default Bye;

Import them both into “index.js” and add them to the render..

import Hi from './Hi';

import Bye from './Bye'; ReactDOM.render((

<Router>

<Route path="/" render={Test} />

<Route exact path="/one" render={One} />

<Route exact path="/punch" render={Punch} />

<Route exact path="/hi" component={Hi} />

<Route exact path="/bye" component={Bye} />

</Router>),

document.getElementById('root')

);

For components you change the word render= to component= . It would still work as render though. Both “Hi” and “Bye” here work exactly like “One” and “Punch”.

Now add NavLink, which change the url of the browser when we click on different parts.

Import NavLink:

import {BrowserRouter as Router, Route, NavLink} from 'react-router-dom'

Create a NavBar which will link to the different paths and add it to the top of the render.

const Navbar = () => {

return (

<div>

<NavLink to="/" exact >Test</NavLink>

<NavLink to="/one" exact >ONE</NavLink>

<NavLink to="/punch" exact >Punch</NavLink>

<NavLink to="/hi" exact >Hi</NavLink>

<NavLink to="/bye" exact >Bye</NavLink>

</div>

)

} ReactDOM.render((

<Router>

<Navbar />

<Route path="/" render={Test} />

<Route exact path="/one" render={One} />

<Route exact path="/punch" render={Punch} />

<Route exact path="/hi" component={Hi} />

<Route exact path="/bye" component={Bye} />

</Router>),

document.getElementById('root')

);

Now everywhere you will see the list of links, and if you click on them not only will the page show the one you clicked on, but the url at the top will change as well!

You can also use the routes to wrap other things, such as buttons, which when clicked will have the same effect.

const Test = () => {

return (

<div>

Test

<NavLink to="/one" exact >

<button >ONE</button>

</NavLink>

<NavLink to="/punch" exact >

<button >PUNCH</button>

</NavLink>

<NavLink to="/hi" exact >

<button >Hi</button>

</NavLink>

<NavLink to="/bye" exact >

<button >Bye</button>

</NavLink>

</div>

)

}

If you add the links and buttons to them, now you have a bunch of buttons which when pressed will change the display! You can use these link buttons to trigger a page and url change to a different component now instead of solely relying on updating state to change it!

One last thing! What if you had something like a shop, where inside the shop area you can click on different things like “buy” or “sell”, and that changes something INSIDE the shop, but the outside area stays the same? In this case you aren’t changing the whole page, only the shop section. This would be a nested link, instead of going from “/shop” to “/buy” you would be going from “/shop” to “/shop/buy”. Let’s set up the components.

Make 2 more files. “Hi2.js” and “Hi3.js”. (These are really creative names right?)

“Hi2” should look like:

import React from 'react'; function Hi2() {

return (

<div>

Hi2

</div>

);

} export default Hi2;

“Hi3.js should look like:

import React from 'react'; function Hi3() {

return (

<div>

Hi3

</div>

);

} export default Hi3;

Now lets update our original “Hi.js” file by importing Hi’s 2 and 3.

import React from 'react';

import Hi2 from './Hi2';

import Hi3 from './Hi3';

import { Link, Route } from 'react-router-dom'; function Hi(props) {

return (

<div>

<Link to={`${props.match.url}/hi2`}>

<button>H2 BUTTON</button>

</Link>

<br/>

<Link to={`${props.match.url}/hi3`}>

<button>H3 BUTTON</button>

</Link> <Route path={`${props.match.url}/hi2`} component={Hi2} />

<Route path={`${props.match.url}/hi3`} component={Hi3} />

</div>

);

} export default Hi;

We are creating two buttons, and wrapping them in Link, which is provided by ‘react-router-dom’, as well as setting up the routes at the bottom. The props passed in contains match.url contains the current link that has brought you to the page so far, so you simply need to add the nested part afterwards.

Now if you click on one of the buttons it should now also display either “Hi2” or “Hi3” depending on which one you clicked!

…

Nothing showed up huh?

Recall back to our index.js. When we set up the route for the “Hi” component we typed:

<Route exact path="/hi" component={Hi} />

We used exact path to make it so if you typed random mumbo-jumbo after “/hi” it would fail. But this actually equally makes it so a nested link will not work! Change “exact path” to just “path”. Everything should now work exactly as expected!

This was the basics of react routing! This now gives you the ability to go back and forward and if people want to jump around to specific pages they are now able to do so by just typing the page they want into the url instead of having to click through things, greatly increasing the user experience! Best of luck making apps with your new knowledge of custom routing!