# Routing

## Routing Props

When `react-router` renders a component, it passes routing-related props: `history`, `location`, and `match`.

```js
<Route path='/blog' component={Blog} />

// In Blog.js...
const Blog = props => {
  console.log(props) // Includes routing-related props

  return (
    <div>I'm a blog</div>
  )
}
```

**Pro tip**: Another way to gain access to routing-related props is to use the higher-order component `withRouter`.

```js
import { withRouter } from 'react-router-dom'

// ...

export default withRouter(Component)
```

## Link Component

The `Link` component basically renders an anchor component and prevents the default behaviour, re-rendering the DOM instead of navigating to the new link and losing state. Here's some useful tips...

You can pass an object instead of a string:

```js
<Link to={{
  pathname: '/login',
  hash: '#start',
  search: '?new-user=true'
}}>
  Log In
</Link>
```

By default, the path you provide is *absolute*, appending it to the root domain. To make it relative, just use routing-related props:

```js
// In Blog.js
<Link to={{
  pathname: this.props.match.url + '/login' // becomes '/blog/login'
}}>
  Log into Blog
</Link>
```

If you want to add styling to your *active* links, use `NavLink` instead:

```js
<NavLink
  to='/login'
  exact // important!
  activeClassName='activeLink' // defaults to 'active'
  activeStyle={{
    color: 'red'
  }}
>
  Log In
</NavLink>
```

### Navigating programmatically

Sometimes, instead of using `Link` to immediately navigate to a URL, we want to *first* run some code and *then* navigate to the URL.

In this case, we can programmatically navigate to a URL using the `history` prop provided:

```js
<Component
  onClick={() => {
    // Do stuff first and then...
    this.props.history.push({ pathname: '/new-url' })
  }} />
```

**Note**: Recall how browser history is like a linked list. By pushing to the end of the list, we're navigating to a new page by adding it to history.

## Route Parameters

Suppose we want to display a blog post with the url `https://blog.com/my-blog-post`, using `my-blog-post` as the slug used to query the blog post contents.

Here's how we can access the parameter:

```js
<Route path='/:slug' exact component={Post} />

// In Post.js...
async componentDidMount() {
  const postData = await getPost(this.props.match.params.slug)
  // ...
}
```

By marking our `:slug` value as a dynamic value, we have access to `slug` as a routing-related prop.

## Using Switch

When implementing multiple `Route` components, it's common to accidentally render more components than you want.

The `Switch` component helps with this. Like the `switch` statement, it renders the first `Route` that matches the path visited:

```js
<Switch>
  <Route path='/' exact component={Home} />
  <Route path='/blog' component={Blog} >
</Switch>
```

## Nested Routes

It's possible to have a `Route` component *inside* another `Route` component. However, it's important to understand that the parent `Route` needs to remain rendered when you navigate to the child `Route`.

The below example will not work because when you navigate to `/:slug`, `Blog` will unmount because the route doesn't match `/blog`. And because the child `Route` is part of `Blog`, it will also unmount.

```js
// Parent: App.js
<Route path='/blog' component={Blog} />

// Child: Blog.js
<Route path='/:slug' component={Post} />
```

To solve this, it's better to utilize a *relative path* (as mentioned earlier). The below example will work because `this.props.match.url` will include `/blog` in the URL.

```js
// Parent: App.js
<Route path='/blog' component={Blog} />

// Child: Blog.js
<Route path={this.props.match.url + '/:slug'} component={Post} />
```


---

# 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://notes.danfitz.com/javascript/reactcompleteguide/9-routing.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.
