How to do it...

In this recipe, we are going to create a simple Notes component to display all our notes when we visit the /notes route, but we will show one note when the user visits /notes/:noteId (we will filter the note using noteId):

  1. We need to create a new component called Notes (src/components/Notes/index.jsx), and this is the skeleton of our Notes component:
    import React, { Component } from 'react';
import './Notes.css';
class Notes extends Component {
constructor() {
super();

// For now we are going to add our notes to our
// local state, but normally this should come
// from some service.

this.state = {
notes: [
{
id: 1,
title: 'My note 1'
},
{
id: 2,
title: 'My note 2'
},
{
id: 3,
title: 'My note 3'
},
]
};
}
render() {
return (
<div className="Notes">
<h1>Notes</h1>
</div>
);
}
}
export default Notes;
File: src/components/Notes/index.jsx
  1. The CSS file is as follows:
    .Notes ul {
list-style: none;
margin: 0;
margin-bottom: 20px;
padding: 0;
}

.Notes ul li {
padding: 10px;
}

.Notes a {
color: #555;
text-decoration: none;
}

.Notes a:hover {
color: #ccc;
text-decoration: none;
}
File: src/components/Notes/Notes.css
  1. Once we have created our Notes component, we need to import it into our src/routes.jsx file:
// Dependencies
import React from 'react';
import { Route, Switch } from 'react-router-dom';

// Components
import App from './components/App';
import About from './components/About';
import Contact from './components/Contact';
import Home from './components/Home';
import Notes from './components/Notes';
import Error404 from './components/Error/404';

const AppRoutes = () => (
<App>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/about" component={About} exact />
<Route path="/contact" component={Contact} exact />
<Route path="/notes" component={Notes} exact />
<Route component={Error404} />
</Switch>
</App>
);

export default AppRoutes;
File: src/routes.jsx
  1. Now we can see our Notes component if we go to the /notes URL:
  1. Now that our Notes component is connected to React Router, let's render our notes as a list:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import './Notes.css';

class Notes extends Component {
constructor() {
super();

this.state = {
notes: [
{
id: 1,
title: 'My note 1'
},
{
id: 2,
title: 'My note 2'
},
{
id: 3,
title: 'My note 3'
},
]
};
}

renderNotes = notes => (
<ul>
{notes.map((note, key) => (
<li key={key}>
<Link to={`/notes/${note.id}`}>{note.title}</Link>
</li>
))}
</ul>
);

render() {
const { notes } = this.state;

return (
<div className="Notes">
<h1>Notes</h1>

{this.renderNotes(notes)}
</div>
);
}
}

export default Notes;
File: src/components/Notes/index.jsx

  1. You may have noticed that we are using <Link> (this will generate an <a> tag) component that points to /notes/notes.id, and this is because we are going to add a new nested route into our src/routes.jsx file to match the id of the note:
// Dependencies
import React from 'react';
import { Route, Switch } from 'react-router-dom';

// Components
import App from './components/App';
import About from './components/About';
import Contact from './components/Contact';
import Home from './components/Home';
import Notes from './components/Notes';
import Error404 from './components/Error/404';

const AppRoutes = () => (
<App>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/about" component={About} exact />
<Route path="/contact" component={Contact} exact />
<Route path="/notes" component={Notes} exact />
<Route path="/notes/:noteId" component={Notes} exact />
<Route component={Error404} />
</Switch>
</App>
);

export default AppRoutes;
File: src/routes.jsx
  1. React Router has a special prop called match, which is an object that includes all the information about our executed route, and if we have parameters, we are going to be able to see them in the match object, like this:
render() {
// Let's see what contains our props object.
console.log(this.props);

// We got the noteId param from match object.
const { match: { params: { noteId } } } = this.props;
const { notes } = this.state;

// By default our selectedNote is false
let selectedNote = false;

if (noteId > 0) {
// If the note id is higher than 0 then we filter it from our
// notes array.

selectedNote = notes.filter(
note => note.id === Number(noteId)
);
}

return (
<div className="Notes">
<h1>Notes</h1>

{/* We render our selectedNote or all notes */}
{this.renderNotes(selectedNote || notes)}
</div>
);
}
File: src/components/Notes/index.jsx
  1. The match prop looks like this.