There are certain things we just can’t build applications without: routing is one of them. Routing is necessary when switching between components in an application. React Router is one of many options you have when it comes to implementing routing in React applications. React Router continues to receive constant updates and is now at v4.x which is readily compatible with React v16.
In this tutorial, we’ll go through the vital concepts needed to get started with React Router 4. We’ll set up our project with create-react-app which provides a quick way to get a react environment up and running.
Preparing our application
#React App Setup
At this point we’ll need to have create-react-app installed. If you haven’t done this yet, run this command to install it globally:
npm install -g create-react-app
Now that we have create-react-app installed. The next step is to initialize our application. To do this run
create-react-app demo-router
In this case, demo-router
is the name of our application, create-react -app will take care of setting up our base folder structure which will look something like this
|---public
|------favicon.ico
|------index.html
|------manifest.json
|---src
|------app.css
|------app.js
|------app.test.js
|------index.css
|------index.js #
|------logo.svg
|------registerServiceWorker.js
|---.gitignore
|---package.json
|---README.md
|---yarn.lock
We’ll be using Semantic UI React which is a great styling framework with really good documentation that I recommend checking out. This will help us make use of a number of pre-built components to speed up our development process.
We’ll also be using yarn as our default package manager. Yarn is a great alternative to npm as it locks down dependency versions — a feature that was added to recent versions of npm. Yarn is also the default package manager for create-react-app. If you don’t have yarn yet, you can find the installation instructions here
Naturally, the first step would be to install the semantic-ui-react npm package. To do so run:
yarn add semantic-ui-react
Great! Now we can import components provided by the team at Semantic UI and customize them to our liking. But first we need to add the Semantic UI CSS to our project. So paste the following in your index.html
file within the public folder.
// index.html
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.12/semantic.min.css"></link>
For this project you will need the image assets located here
Now let’s create a components
folder under the src
directory under which we’ll have the various components we’ll be using as samples, cd into the components folder and run the following command
touch myFirstComponent.jsx
Now add the following code into myFirstComponent.jsx
// myFirstComponent.jsx
import React from 'react'
import { Card, Icon } from 'semantic-ui-react'
const description = [
'Anakin is a Jedi string with the force.',
'Qui Gon Jin brought him before the council believing him to be the chosen one.',
].join(' ')
const CardExtraContent = () => (
<Card>
<Card.Content header='About Anakin' />
<Card.Content description={description} />
<Card.Content extra>
<Icon name='user' />
4 Friends
</Card.Content>
</Card>
)
export default CardExtraContent
This is a sample card that we’ll use as our first view. Now let’s create another sample component and call it articleItem.jsx
.
// articleItem.jsx
import React from 'react'
import { Button, Icon, Item, Label, Image } from 'semantic-ui-react'
const paragraph = <Image src='/assets/images/wireframe/short-paragraph.png' />
const ItemDivided = () => (
<Item.Group divided>
<Item>
<Item.Image src='/assets/images/wireframe/image.png' />
<Item.Content>
<Item.Header as='a'>The Force Awakens</Item.Header>
<Item.Meta>
<span className='cinema'>IMAX</span>
</Item.Meta>
<Item.Description>{paragraph}</Item.Description>
<Item.Extra>
<Label>IMAX</Label>
<Label icon='globe' content='Additional Languages' />
</Item.Extra>
</Item.Content>
</Item>
<Item>
<Item.Image src='/assets/images/wireframe/image.png' />
<Item.Content>
<Item.Header as='a'>Rogue One</Item.Header>
<Item.Meta>
<span className='cinema'>Fox Cinema</span>
</Item.Meta>
<Item.Description>{paragraph}</Item.Description>
<Item.Extra>
<Button primary floated='right'>
Buy tickets
<Icon name='right chevron' />
</Button>
<Label>Limited</Label>
</Item.Extra>
</Item.Content>
</Item>
<Item>
<Item.Image src='/assets/images/wireframe/image.png' />
<Item.Content>
<Item.Header as='a'>The Last Jedi</Item.Header>
<Item.Meta>
<span className='cinema'>IFC</span>
</Item.Meta>
<Item.Description>{paragraph}</Item.Description>
<Item.Extra>
<Button primary floated='right'>
Buy tickets
<Icon name='right chevron' />
</Button>
</Item.Extra>
</Item.Content>
</Item>
</Item.Group>
)
export default ItemDivided
Awesome! Now we have our first two components to switch between. To do this though, we will use a navbar component. Create a navBar.jsx
file and add the following code to it.
// navBar.jsx
import React, { Component } from 'react'
import { Menu } from 'semantic-ui-react'
import logo from '../logo.svg'
class NavBar extends Component {
state = {}
handleItemClick = (e, { name }) => this.setState({ activeItem: name })
render() {
const { activeItem } = this.state
return (
<Menu stackable>
<Menu.Item>
<img src={logo} />
</Menu.Item>
<Menu.Item
name='feed'
active={activeItem === 'feed'}
onClick={this.handleItemClick}
href='/feed'
>
Feed
</Menu.Item>
<Menu.Item
name='card'
active={activeItem === 'card'}
onClick={this.handleItemClick}
href='/card'
>
Card
</Menu.Item>
</Menu>
)
}
}
export default NavBar
Now let’s add the navbar we’ve just created to our app. We can do this by editing App.js
. We’ll need to remove the code added by create-react-app and replace it with our nav bar component. Once done, the file should look like this:
// app.js
import React, { Component } from 'react';
import './App.css';
import NavBar from './components//navBar';
class App extends Component {
render() {
return (
<div >
<NavBar />
<div>
{this.props.children}
</div>
</div>
);
}
}
export default App;
You will notice we also added {this.props.children}
. This is where the child components we declare in our router will be rendered. Now look at your app in the browser, it should look something like this:
Setting Up Our Router
Now that we are all set up, let’s get to the main reason we are here, setting up our router. Naturally, the first step will be to install dependencies.
yarn add react-router react-router-dom
Now let’s create our a routes.js
file where we’ll declare our routes:
cd src/
touch routes.jsx
And next we declare our routes in routes.jsx
// routes.jsx
import React from 'react'
import { Route, Switch } from 'react-router-dom'
import App from './App'
import Feed from './components/feedComponent';
import Card from './components/myFirstComponent';
const Routes = () => (
<App>
<Switch>
<Route exact path="/feed" component={Feed} />
<Route exact path="/card" component={Card} />
</Switch>
</App> )
export default Routes
We have wrapped our routes inside the App component here, this means it will be the parent component and all components will be rendered within it as child components. The switch statement above is one of a number of route declaration options provided by React Router v4. It is easy to use and great when it comes to authenticated routes, which we will cover later in this tutorial.
Now that we have already declared our routes we’ll need to edit the app entry point to make use of our newly declared routes. We’ll need to make some changes to index.js
and have it render our routes component wrapped inside react-router-dom’s BrowserRouter component. BrowserRouter enables our app to make use of the HTML 5 history API to sync our UI with the URL.
Making these changes, the file should now look like this:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import registerServiceWorker from './registerServiceWorker';
import Routes from './routes';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter >
<Routes />
</BrowserRouter >
, document.getElementById('root'));
registerServiceWorker();
Now fire up the app and click on any of the links on the NavBar. It redirects to the specific components. Pretty cool, right?
Authenticated Routes
Most applications will feature protected routes that require the user to login to gain access. You could do this in a number of ways. I personally like Auth0 which provides awesome social login via Google, Github, Windows, you can check it out here. Follow this tutorial to set up Auth0 for your React App. Note that if you had previously worked on integrating GitHub with an Auth0 application you may have to use a different port from the previous application to allow differentiation of the two applications.
Once Auth0 is set up we’ll need to define a method in our routes.js file to handle authentication. After thar we’ll use the ternary operator(?) to choose which components are rendered for authenticated users. With these changes, your routes.jsx
file should now look like this:
import React from 'react';
import { Route, Switch, Redirect } from 'react-router-dom'
import App from './App';
import Feed from './components/feedComponent';
import Card from './components/myFirstComponent';
import Auth from './utils/AuthService';
import Authed from './components/Authed';
import Callback from './components/Callback';
import history from './utils/History';
const auth = new Auth();
const handleAuthentication = (nextState, replace) => {
if (/access_token|id_token|error/.test(nextState.location.hash)) {
auth.handleAuthentication();
}
}
const Routes = () => (
<App>
<Switch>
<Route exact path="/feed" component={Feed} />
<Route exact path="/card" component={Card} />
<Route exact path="/authed" render={(props) => (!auth.isAuthenticated() ? ( <Redirect to="/feed"/> ): (<Authed auth={auth} {...props} />))} />
<Route exact path="/callback" render={(props) => {
handleAuthentication(props);
return <Callback {...props} />
}}/>
</Switch>
</App> )
export default Routes
The link to the authed
component should be added to the NavBar as well. Now try clicking on authed on the NavBar. You should see something like this:
URL Parameters
You may sometimes need to pass and access parameters in your applications and this is pretty simple with React Router 4. Say for instance we wanted to have a route that takes our name as a parameter and says hello to us. We can add it to our routes file as below
<Route exact path="/hello/:name" component={Hello} />
In this case :name
is a dynamic variable whose value is accessible to our component via props by as this.props.match.params.name
. Let’s use this in a component:
// Hello.jsx
import React, { Component } from 'react'
import { Card } from 'semantic-ui-react'
class Hello extends Component {
render(){
const name = this.props.match.params.name;
return(
<Card
header={`Hello ${name}`}
description={`This route uses your name in the URL params. You are ${name}`}
/>
)
}
}
export default Hello
In your browser try entering the URL we added to the routes file replacing the name parameter with your name, hit enter and you should see your name on the card rendered on your browser which in my case looked like this:
Conclusion
Congratulations! You are now equipped with the basics you need to get started with React Router v4, with what we’ve covered you should be able to set up routing in your React applications easily. You may also be interested in checking out this tutuorial which covers React Router 3.
Source: Scotch.io