# React Router

## Simple React App with Routing

A simple React App with Router

{% tabs %}
{% tab title="Home.js" %}

```jsx
import React from "react"

function Home() {
    return (
        <h1>Home Page</h1>
    )
}

export default Home
```

{% endtab %}

{% tab title="About.js" %}

```jsx
import React from "react"

function About() {
    return (
        <h1>About Page</h1>
    )
}

export default About
```

{% endtab %}

{% tab title="Contact.js" %}

```jsx
import React from "react"

function Contact() {
    return (
        <h1>Contact Page</h1>
    )
}

export default Contact
```

{% endtab %}

{% tab title="App.js" %}

```jsx
import React from "react"

import Home from "./Home"
import About from "./About"
import Contact from "./Contact"
import {Link, Switch, Route} from "react-router-dom"

function App() {    
    return (
        <div>
            <nav>
                <Link to="/">Home</Link>
                <Link to="/about">About</Link>
                <Link to="/contact">Contact</Link>
            </nav>
            
            <Switch>
                // 'exact' refers to the exact url we want the route to go
                <Route exact path="/">
                    <Home />
                </Route>
                <Route path="/about">
                    <About />
                </Route>
                <Route path="/contact">
                    <Contact />
                </Route>
            </Switch>
        </div>
    )
}

export default App
```

{% endtab %}
{% endtabs %}

## Dynamic Nested Routing with `useParams`

A React App with Dynamic Nested Routing

{% tabs %}
{% tab title="Home.js" %}

```jsx
import React from "react"

function Home() {
    return (
        <h1>Home Page</h1>
    )
}

export default Home
```

{% endtab %}

{% tab title="servicesData.js" %}

```jsx
export default [
    {
        "name": "Lawn Mowing",
        "price": 30,
        "_id": "1",
        "description": "Have a carpet-like lawn without any work."
    },
    {
        "name": "Leaf Raking",
        "price": 50,
        "_id": "2",
        "description": "Remove those pesky dead tree parts from your property."
    },
    {
        "name": "Weeding",
        "price": 50,
        "_id": "3",
        "description": "Don't let the invaders ruin your yard."
    },
    {
        "name": "Sprinkler repair",
        "price": 100,
        "_id": "4",
        "description": "Keep your irrigation system top-notch."
    }
]
```

{% endtab %}

{% tab title="ServicesList.js" %}

```jsx
import React from "react"
import servicesData from "./servicesData"
import {Link} from "react-router-dom"

function ServicesList() {
    const services = servicesData.map(service => (
        <h3 key={service._id}>
            <Link to={`/services/${service._id}`}>{service.name}</Link> - ${service.price}
        </h3>
    ))
    return (
        <div>
            <h1>Services List Page</h1>
            {services}
        </div>
    )
}

export default ServicesList
```

{% endtab %}

{% tab title="ServiceDetail.js" %}

```jsx
import React from "react"
import {useParams} from "react-router-dom"
import servicesData from "./servicesData"

function ServiceDetail(props) {
    // The useParams() hook helps us to access the URL parameters from a current route
    const {serviceId} = useParams()
   
    // Retrieve all items from a Service that matches the ID we passed
    const thisService = servicesData.find(service => service._id === serviceId)
    
    return (
        <div>
            <h1>Service Detail Page</h1>
            <h3>{thisService.name} - ${thisService.price}</h3>
            <p>{thisService.description}</p>
        </div>
    )
}

export default ServiceDetail
```

{% endtab %}

{% tab title="App.js" %}

```jsx
import React from "react"
import Header from "./components/Header"
import Home from "./pages/Home"
import ServicesList from "./pages/services/ServicesList"
import ServiceDetail from "./pages/services/ServiceDetail"

import {Switch, Route} from "react-router-dom"

function App() {    
    return (
        <div>
            <Header />
            
            <Switch>
                <Route exact path="/">
                    <Home />
                </Route>
                <Route exact path="/services" >
                    <ServicesList />
                </Route>
                // we put ':' to designate nested route  
                <Route path="/services/:serviceId" >
                    <ServiceDetail />
                </Route>
            </Switch>
        </div>
    )
}

export default App
```

{% endtab %}
{% endtabs %}

## Add/Update Routing Path & Url with `useRouteMatch`&#x20;

We can avoid hard-coding to specify a router `path` and `url`by using `useRouteMatch`

{% tabs %}
{% tab title="Header.js" %}

```jsx
import React from "react"
import {Link} from "react-router-dom"

function Header() {
    return (
        <header>
            <ul>
                <li><Link to="/">Home</Link></li>
                <li><Link to="/profile">Profile</Link></li>
            </ul>
        </header>
    )
}

export default Header
```

{% endtab %}

{% tab title="Profile.js" %}

```jsx
import React from "react"
import {Link, Switch, Route, useRouteMatch} from "react-router-dom"

import Settings from "./Settings"
import Info from "./Info"

function Profile() {
    // useRouteMatch provides aceess to `match` object and it's properties `path` and `url`
    const {path, url} = useRouteMatch()
    
    return (
        <div>
            <h1>Profile Page</h1>
            <ul>
                <li><Link to={`${url}/info`}>Profile Info</Link></li>
                <li><Link to={`${url}/settings`}>Profile Settings</Link></li>
            </ul>
            
            <Switch>
                <Route path={`${path}/info`}>
                    <Info/>
                </Route>
                <Route path={`${path}/settings`}>
                    <Settings/>
                </Route>
            </Switch>
        </div>
    )
}

export default Profile
```

{% endtab %}

{% tab title="Info.js" %}

```jsx
import React from "react"

function Info() {
    return (
        <section>
            <h1>Profile Info</h1>
            <p>Hello, user! Tons of useful info here...</p>
        </section>
    )
}

export default Info
```

{% endtab %}

{% tab title="Settings.js" %}

```jsx
import React from "react"

function ProfileSettings() {
    return (
        <section>
            <h1>Profile settings</h1>
            <input type="password"/>
            <button>Change</button>
        </section>
    )
}

export default ProfileSettings
```

{% endtab %}

{% tab title="Home.js" %}

```jsx
import React from "react"

function Home() {
    return (
        <h1>Home Page</h1>
    )
}

export default Home
```

{% endtab %}

{% tab title="App.js" %}

```jsx
import React from "react"
import Header from "./components/Header"
import Footer from "./components/Footer"
import Home from "./pages/Home"
import Profile from "./pages/profile/Profile"

import {Switch, Route} from "react-router-dom"

function App() {    
    return (
        <div>
            <Header />
            
            <Switch>
                <Route exact path="/">
                    <Home />
                </Route>
                <Route path="/profile">
                    <Profile/>
                </Route>
            </Switch>
            
            <Footer />
        </div>
    )
}

export default App

```

{% endtab %}
{% endtabs %}

## Go Back or Forward and Jump to Different Urls with `useHistory`

{% tabs %}
{% tab title="Home.js" %}

```jsx
import React from "react"

function Home() {
    return (
        <h1>Home Page</h1>
    )
}

export default Home
```

{% endtab %}

{% tab title="ServicesData.js" %}

```jsx
export default [
    {
        "name": "Lawn Mowing",
        "price": 30,
        "_id": "1",
        "description": "Have a carpet-like lawn without any work."
    },
    {
        "name": "Leaf Raking",
        "price": 50,
        "_id": "2",
        "description": "Remove those pesky dead tree parts from your property."
    },
    {
        "name": "Weeding",
        "price": 50,
        "_id": "3",
        "description": "Don't let the invaders ruin your yard."
    },
    {
        "name": "Sprinkler repair",
        "price": 100,
        "_id": "4",
        "description": "Keep your irrigation system top-notch."
    }
]
```

{% endtab %}

{% tab title="ServicesList.js" %}

```jsx
import React from "react"
import {Link} from "react-router-dom"

import servicesData from "./servicesData"

function ServicesList() {
    const services = servicesData.map(service => (
        <div key={service._id}>
            <h3><Link to={`/services/${service._id}`}>{service.name}</Link> - ${service.price}</h3>
        </div>
    ))
    return (
        <div>
            <h1>Services List Page</h1>
            {services}
        </div>
    )
}

export default ServicesList
```

{% endtab %}

{% tab title="ServiceDetail.js" %}

```jsx
import React from "react"
import {useParams, useHistory} from "react-router-dom"

import servicesData from "./servicesData"

function ServiceDetail() {
    const {serviceId} = useParams()
    // useHistory provides access to properties such as push, go back, replace 
    const history = useHistory()
    const thisService = servicesData.find(service => service._id === serviceId)
    
    function handleClick(){
        console.log("Submitting")
        setTimeout(()=>{
            history.push("/services") // `push` allows us to go to a specific url
        }, 2000)
    }
    
    return (
        <div>
            <h1>Service Detail Page</h1>
            <h3>{thisService.name} - ${thisService.price}</h3>
            <p>{thisService.description}</p>
            <button onClick={handleClick}>Go back to all history</button>
        </div>
    )
}

export default ServiceDetail

```

{% endtab %}

{% tab title="App.js" %}

```jsx
import React from "react"
import Header from "./components/Header"
import Home from "./pages/Home"
import ServicesList from "./pages/services/ServicesList"
import ServiceDetail from "./pages/services/ServiceDetail"

import {Switch, Route} from "react-router-dom"

function App() {    
    return (
        <div>
            <Header />
            
            <Switch>
                <Route exact path="/" component={Home}/>
                <Route exact path="/services" component={ServicesList}/>
                <Route path="/services/:serviceId" component={ServiceDetail}/>
            </Switch>
        </div>
    )
}

export default App
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
if we want to just click a button or a link and go to another location, use the `Link` tag. However, if we need to perform an operation such as running some JavaScript before redirecting to another page (e.g. in a login page) then `useHistory` is the way to go.
{% endhint %}

## Get Access to Location Information with`useLocation`

`useLocation` gives us easy access to information about the location in our app (i.e. the path that we are currently at).

```jsx
import React from "react"
import {Link, useLocation} from "react-router-dom"

import servicesData from "./servicesData"

function ServicesList() {
    // useLocation provides access to properties such as current pathname, search query string, state 
    const location = useLocation()
    console.log(location)
    
    const services = servicesData.map(service => (
        <div key={service._id}>
            <h3><Link to={`/services/${service._id}`}>{service.name}</Link> - ${service.price}</h3>
        </div>
    ))
    return (
        <div>
            <h1>Services List Page</h1>
            {services}
        </div>
    )
}

export default ServicesList
```

## Change Route Automatically with `Redirect`

This can be useful when dealing with authentication, for example by sending a user back to the login page if they fail to provide accurate login credentials.

```jsx
import React, {useState} from "react"
import {Link, Switch, Route, Redirect} from "react-router-dom"

function App() {
    const [isLoggedIn, setIsLoggedin] = useState(false)        
    return (
        <div>
            <Link to="/">Home</Link>
            <Link to="/private">Private</Link>
            
            <Switch>
                <Route exact path="/">
                    <h1>This is Home Page</h1>
                </Route>
                
                <Route path="/private">
                {
                    isLoggedIn ? 
                    <h1>This is a private page and user needs to be logged in here!</h1> :
                    <Redirect to="/login" />
                
                }
                    </Route>
                
                <Route path="/login">
                    <button onClick={() => setIsLoggedin(true)}>Log in</button>
                </Route>
            </Switch>
        </div>
    )
}

export default App
```
