# Next Stop - React Router | SPA

![](/files/-LisvAcGZR3KZpI4pTQc)

React doesn't come with a built-in router, but we can easily achieve routing with the `react-router-dom` library. **Routing** is how a web applications direct traffic.

Example: If you go to **dataworld.com**, you end up on my home page. If you go to **dataworld.com/me**, you're redirected to my about me page. If you go to **dataworld.com/categories/javascript** or **dataworld.com/categories/css**, you end up on a category listing page. The routes for these pages look something like this:

* `/` - root
* `/:page_id` - page
* `/categories/:category_id` - category

I'm not actually making a folder called `categories` and filling it with a bunch of files like `javascript.html` or `css.html`, I just have one template and the router knows to direct to the proper template. Once it gets to the template, it can pull from the URL to know which variables to display - for example, JavaScript or CSS related posts.

This website also happens to be a **Single Page Application** (or SPA) - only one page is loaded, and every click to a new page loads some additional JSON data, but does not actually request a new resource like loading `index.html` and `about-me.html` would.

I'm going to show you how to set up a simple SPA in React with `react-router-dom`, and pull in data dynamically through the URL. Below is the source of the completed project if you get lost along the way.

**Prerequisites**

* Read [Getting Started with React](https://www.taniarascia.com/getting-started-with-react/) or [Build a React App with Hooks](https://www.taniarascia.com/crud-app-in-react-with-hooks/) if you don't know React or React Hooks yet.
* Read [How to Connect to an API in JavaScript](https://www.taniarascia.com/how-to-connect-to-an-api-with-javascript/) if you don't know how to work with APIs at all.

### Installation <a href="#installation" id="installation"></a>

Create a new React app.

```
npx create-react-app react-router-example
Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...
```

Our project has two dependencies - `react-router-dom` for the router, and `axios` for making API calls.

```
npm install react-router-dom axios
```

or

```
yarn add react-router-dom axios
```

### Browser Router <a href="#browser-router" id="browser-router"></a>

To use `react-router-dom`, we need to wrap our entire `App` component in [`BrowserRouter`](https://reacttraining.com/react-router/web/api/BrowserRouter). There are two types of routers:

* `BrowserRouter` - makes pretty URLs like `example.com/about`.
* `HashRouter` - makes URLs with the `octothorpe` (or hashtag, if you will) that would look like `example.com/#about`.

Let's use `BrowserRouter`.src/index.js

```
import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
import App from './App'

render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.querySelector('#root')
)
```

### Route and Switch <a href="#route-and-switch" id="route-and-switch"></a>

Now in `App.js`, we can decide on the routes we want to use and direct accordingly. We'll use `Route`and `Switch` for this task.

* `Switch` - Groups all your routes together, and ensures they take precedence from top-to-bottom.
* `Route` - Each individual route.

App.js

```
import React from 'react'
import { Route, Switch } from 'react-router-dom'
// We will create these two pages in a moment
import HomePage from './pages/HomePage'
import UserPage from './pages/UserPage'

export default function App() {
  return (
    <Switch>
      <Route exact path="/" component={HomePage} />
      <Route path="/:id" component={UserPage} />
    </Switch>
  )
}
```

We're matching the root route (`/`) to `HomePage`, and dynamically matching any other page to `UserPage`. I only have one route for this simple example, but you could do more like this:

```
<Switch>
  <Route exact path="/" component={HomePage} />
  <Route path="/:id" component={UserPage} />
  <Route path="/categories" component={CategoriesPage} />
  <Route path="/categories/:id" component={IndividualCategoryPage} />
</Switch>
```

This would ensure that `dataworld.com/categories` would go to a page listing all categories, but `dataworld.com/categories/javascript` would go to a completely different template for the individual category listing.

### Link <a href="#link" id="link"></a>

In order to link to a page within the SPA, we'll use [`Link`](https://reacttraining.com/react-router/web/api/Link). If we used the traditional `<a href="/route">`, it would make a completely new request and reload the page, so we have `Link`to help us out.src/pages/HomePage.js

```
import React, { Component } from 'react'
import { Link } from 'react-router-dom'

export default function HomePage() {
  return (
    <div className="container">
      <h1>Home Page</h1>
      <p>
        <Link to="/taniarascia">taniarascia</Link> on GitHub.
      </p>
    </div>
  )
}
```

So now I'm going to my first route, the root route which is loading `HomePage`, and I see the content and the link.

![router home page](https://www.taniarascia.com/static/7a0770038ff804dfb3c300de6dc61183/06bbf/router-home-page.png)

### Dynamic Route Parameter <a href="#dynamic-route-parameter" id="dynamic-route-parameter"></a>

Our `Link` is navigating to `/dataworld`, which will match the `/:id` parameter in `Route`. In order to dynamically get the content from the URL - in this case, `taniarascia` - we'll use `match.params.id`from the `props`.

I'm going to use that parameter to make a call to the GitHub API and retrieve my data. In this example I'll be using Hooks, so if you're not familiar with them, please read [Building a CRUD App with Hooks](https://www.taniarascia.com/crud-app-in-react-with-hooks/).src/pages/UserPage.js **\<props.match.params.id>**

```
import React, { useState, useEffect } from 'react'
import axios from 'axios'

export default function UserPage(props) {
  // Setting initial state
  const initialUserState = {
    user: {},
    loading: true,
  }

  // Getter and setter for user state
  const [user, setUser] = useState(initialUserState)

  // Using useEffect to retrieve data from an API (similar to componentDidMount in a class)
  useEffect(() => {
    const getUser = async () => {
      // Pass our param (:id) to the API call
      const { data } = await axios(`https://api.github.com/users/${props.match.params.id}`)

      // Update state
      setUser(data)
    }

    // Invoke the async function
    getUser()
  }, []) // Don't forget the `[]`, which will prevent useEffect from running in an infinite loop

  // Return a table with some data from the API.
  return user.loading ? (
    <div>Loading...</div>
  ) : (
    <div className="container">
      <h1>{props.match.params.id}</h1>

      <tab
        <tbody>
          <tr>
            <td>{user.name}</td>
            <td>{user.location}</td>
            <td>
              <a href={user.blog}>{user.blog}</a>
            </td>
            <td>{user.followers}</td>
          </tr>
        </tbody>
      </table>
    </div>
  )

```

### &#x20;<a href="#conclusion" id="conclusion"></a>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tkssharma.gitbook.io/react-training/day-05/next-stop-react-router-or-spa.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
