Introducing routing to our app

Most apps as they grow need to support routing. Routing in the context of frameworks is the binding of components to URLs so that when a request comes in for a URL such as /about, an About component is rendered into the view. React has an entire library dedicated to routing and we'll explore it now.

Learning Objectives

How React routing works

React Router, and dynamic, client-side routing, allows us to build a single-page web application with navigation without the page refreshing as the user navigates 🤯. React Router uses component structure to call components, which display the appropriate information.

By preventing a page refresh, and using Router or Link, which is explained in more depth below, the flash of a white screen or blank page is prevented. This is one increasingly common way of having a more seamless user experience. React router also allows the user to utilize browser functionality like the back button and the refresh page while maintaining the correct view of the application.

Forget what you know about using <a> tags to navigate with links. Say hello to the <Link> component. We are going to aim to create individual pages for each product and be able to browse through the stock by moving backwards and forwards between the landing page, a product page, and back again.

Install and set up

npm install react-router-dom

When using React router, we render components inside a <Router> component. Since we don't want the home page content to render on other pages, this raises the question: how do we render the current content on the home page into the router view?

One solution is to introduce a Home component. This component will be responsible for the main home page content and will render the three products that are currently rendered in the App component.

Remove the home content from App.js and add it into a Home component in a new file. You should end up with something like this in Home.js:

import { useState } from 'react'
import data from './products.json'
import { Product } from './Product'

function Home() {
  const [cart, setCart] = useState([])

  const addToCart = product => {
    setCart([...cart, product])
  }

  return (
    <div className="App">
      {data.products.map(product => <Product key={product.productId} product={product} addToCart={addToCart} />)}
    </div>
  );
}

export default Home;

and this in App.js
top tip - check everything still works before introducing routing.

import Home from './Home'

function App() {
  return (
    <Home />
  );
}

export default App;

Re-imagining our app

Now lets create some navigation and have that navigation render different views in our app. Update App.js to now include some navigation links and some components for other pages.

import Home from './Home'
import { BrowserRouter as Router, Link, Switch, Route } from 'react-router-dom'

function App() {
  return (
    <Router>
      <header>
        <nav>
          <Link to="/">Home</Link>
          <Link to="/about">About</Link>
          <Link to="/contact">Contact</Link>
        </nav>
      </header>
      <Switch>
        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
}

export default App;

Assignment - Coding challenge

Part one

You'll notice that the new router links actually work, but no component is rendered on a click. Your coding challenge is to create two new routes for /about and /contact and two new components About and Contact that are loaded into the router view when requested.

top tip the order of the components inside Switch matters. Have your '/' Home route be the LAST one.

Part two

Add some basic markup/content to your About and Contact pages for stakeholder review!

Additional resources