# react-router-transition-switch

[![CircleCI](https://circleci.com/gh/jcoreio/react-router-transition-switch.svg?style=svg)](https://circleci.com/gh/jcoreio/react-router-transition-switch)
[![Coverage Status](https://codecov.io/gh/jcoreio/react-router-transition-switch/branch/master/graph/badge.svg)](https://codecov.io/gh/jcoreio/react-router-transition-switch)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![npm version](https://badge.fury.io/js/react-router-transition-switch.svg)](https://badge.fury.io/js/react-router-transition-switch)

This is a variant of `<Switch>` that's much easier to use with transition components and solves some problems.

The current recommended transition approach for `react-router` is

```js
import { Route, Switch } from 'react-router-dom'
import Fader from 'react-fader'

const MyRoute = () => (
  <Route
    render={({ location }) => (
      <Fader>
        <Switch key={location.key} location={location}>
          <Route path="/red" component={Red} />
          <Route path="/green" component={Green} />
          <Route path="/blue" component={Blue} />
        </Switch>
      </Fader>
    )}
  />
)
```

This has several problems:

1. All `<Switch>`es transition on every `location` change, even if:
   - only the last part of the URL changed and you only want the innermost nested `<Switch>` to transition
   - you have the same component for two different paths and don't want to transition that component
   - you don't want to transition in some case for any other reason
2. You have to pass a `location` to the `<Switch>` for it to work

`react-router-transition-switch` simplifies the above example to

```js
import { Route } from 'react-router-dom'
import Switch from 'react-router-transition-switch'
import Fader from 'react-fader'

const MyRoute = () => (
  <Switch component={Fader}>
    <Route path="/red" component={Red} />
    <Route path="/green" component={Green} />
    <Route path="/blue" component={Blue} />
  </Switch>
)
```

## Differences from `react-router`'s `<Switch>`:

1. You can pass it a `component` or `render` prop. It will use them to wrap the matched `<Route>` if given
2. By default it clones the matched `<Route>` with `key={match.url}` unless you gave the `<Route>` a key yourself.
   This way the `Fader` will only perform a transition when:
   - if you provide `key`s yourself, the matched `<Route>` has a different `key` than the last
   - otherwise, the _matched portion_ of the `location` is different from the last`
3. You can pass it a `createKey` prop, which is a function taking the `(route, match)`
   and returning the key to use.

## `component` example

```js
import React from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Fader from 'react-fader'
import Switch from 'react-router-transition-switch'

// ...
const MyRoute = () => (
  <Router>
    <Switch component={Fader}>
      <Route exact path="/" component={Home} />
      <Route path="/about" component={About} />
      <Route path="/account" component={Account} />
      <Route path="/users/:userId" component={User} />
    </Switch>
  </Router>
)
```

For the location `/users/andy/profile`, the `<Switch>` will render:

```js
<Fader>
  <Route key="/users/andy/profile" path="/users/:userId" component={User} />
</Fader>
```

Notice that it makes `match.url` the `key` of the matched `<Route>`, so that `<Fader>` (or whatever transition component
you use) knows to perform a transition. If you provide custom `key`s on the `<Route>`s you pass to `<Switch>`, it won't
overwrite them.

## `render` example

As with `<Route>`, you may pass a `render` function instead of a `component`:

```js
<Router>
  <Switch
    render={({ children }) => (
      <ReactCSSTransitionGroup
        transitionName="example"
        transitionEnterTimeout={300}
        transitionLeaveTimeout={300}
      >
        {children}
      </ReactCSSTransitionGroup>
    )}
  >
    ...
  </Switch>
</Router>
```

## Preventing transitions in certain cases

If you want to prevent transitions between certain `<Route>`s, give them the same `key`. This will not cause problems
because `<Switch>` only renders one of the child `<Route>`s it was passed, so there will never be duplicate keys during
React's reconciliation step.

```js
<Router>
  <Switch component={Fader}>
    <Route key="home" exact path="/" component={Home} />
    <Route key="orders" exact path="/orders" component={Orders} />
    <Route key="orders" path="/orders/:orderId" component={Orders} />
    <Route key="about" path="/about" component={About} />
  </Switch>
</Router>
```

## Forcing transitions in certain cases

If you have to pass in an array of `<Route>`s, they will already have
keys, hence changes between subroutes will not transition since
`react-router-transition-switch` does not override existing keys with the
`match.url`.

In this case, you can use the `createKey` prop to force a unique key for
every `match`:

```js
<Router>
  <Switch component={Fader} createKey={(child, match) => match.url}>
    {routes}
  </Switch>
</Router>
```
