GithubHelp home page GithubHelp logo

jcoreio / react-router-transition-switch Goto Github PK

View Code? Open in Web Editor NEW
12.0 3.0 0.0 1.33 MB

a variant of <Switch> that's much easier to use with transition components

License: MIT License

JavaScript 100.00%
react-router transitions

react-router-transition-switch's Introduction

react-router-transition-switch

CircleCI Coverage Status semantic-release Commitizen friendly npm version

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

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

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 keys 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

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:

<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 keys 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:

<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.

<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:

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

react-router-transition-switch's People

Contributors

jedwards1211 avatar greenkeeper[bot] avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar sbtly avatar Robert Boes avatar Guilherme Santiago avatar Paul Tiedtke avatar Sam Ward avatar  avatar AlbertGao avatar Pedro Gómez avatar Martin avatar Timon van Spronsen avatar Travis Arnold avatar

Watchers

James Cloos avatar  avatar  avatar

react-router-transition-switch's Issues

IE 11 Incompatibility

The published NPM module for this library is not transpiled to support IE 11. Is this intentional? If not, then please add this preset to a .babelrc file in the root of this project:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "> 0.25%, not dead"
      }
    ]
  ]
}

How do you trigger a "leave" transition?

Given the example from the docs:

<Switch component={Fader}>
  <Route path="/red" component={Red}/>
  <Route path="/green" component={Green} />
  <Route path="/blue" component={Blue} />
</Switch>

The first time the "/red" path is matched, I want to mount it and immediately fade it in. If the route then changes to "/green", then before anything happens, I want the Red component to play its "leave" animation (like "fade out"), and once that's done, then the Green component can play its "enter" animation. How would I manage those transitions with this library?

react-router v5 compatibility

I tried upgrading to react-router v5 and got the following errors:

Warning: Please use `require("react-router").matchPath` instead of `require("react-router/matchPath")`. Support for the latter will be removed in the next major release.

and

You should not use <TransitionSwitch> outside a <Router>
Invariant Violation: You should not use <TransitionSwitch> outside a <Router>
    at invariant (/Users/johnwineman/projects/front-end/node_modules/invariant/invariant.js:40:15)
    at TransitionSwitch.componentWillMount (/Users/johnwineman/projects/front-end/node_modules/react-router-transition-switch/lib/index.js:62:31)
    at processChild (/Users/johnwineman/projects/front-end/node_modules/react-dom/cjs/react-dom-server.node.development.js:2905:16)
    at resolve (/Users/johnwineman/projects/front-end/node_modules/react-dom/cjs/react-dom-server.node.development.js:2795:5)
    at ReactDOMServerRenderer.render (/Users/johnwineman/projects/front-end/node_modules/react-dom/cjs/react-dom-server.node.development.js:3185:22)
    at ReactDOMServerRenderer.read (/Users/johnwineman/projects/front-end/node_modules/react-dom/cjs/react-dom-server.node.development.js:3144:29)
    at renderToString (/Users/johnwineman/projects/front-end/node_modules/react-dom/cjs/react-dom-server.node.development.js:3629:27)
    at request (/Users/johnwineman/projects/front-end/dist/server/map/webpack:/src/server/middleware/render.js:43:20)
    at /Users/johnwineman/projects/front-end/dist/server/map/webpack:/src/util/server.util.js:25:23
    at <anonymous>

This is because your plugin is checking for the router context using the legacy API. I filed remix-run/react-router#6656 to see how we should detect the <Router/> in the new version.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.