Skip to content

Instantly share code, notes, and snippets.

@maisano
Last active September 15, 2023 07:29
Show Gist options
  • Save maisano/8faf4bd123fa9842f4ea to your computer and use it in GitHub Desktop.
Save maisano/8faf4bd123fa9842f4ea to your computer and use it in GitHub Desktop.
Using react-motion with react-router
import React, { PropTypes } from 'react';
import { TransitionMotion, spring } from 'react-motion';
/**
* One example of using react-motion (0.3.0) within react-router (v1.0.0-rc3).
*
* Usage is simple, and really only requires two things–both of which are
* injected into your app via react-router–pathname and children:
*
* <RouteTransition pathname={this.props.pathname}>
* {this.props.children}
* </RouteTransition>
*/
const RouteTransition = React.createClass({
propTypes: {
pathname: PropTypes.string.isRequired
},
willEnter() {
return {
handler: this.props.children,
opacity: spring(0),
scale: spring(0.95)
};
},
willLeave(key, value) {
return {
handler: value.handler,
opacity: spring(0),
scale: spring(0.95)
};
},
getStyles() {
const { children, pathname } = this.props;
return {
[pathname]: {
handler: children,
opacity: spring(1),
scale: spring(1)
}
};
},
render() {
return (
<TransitionMotion
styles={this.getStyles()}
willEnter={this.willEnter}
willLeave={this.willLeave}
>
{interpolated =>
<div>
{Object.keys(interpolated).map(key =>
<div
key={`${key}-transition`}
style={{
position: 'absolute',
opacity: interpolated[key].opacity,
transform: `scale(${interpolated[key].scale})`
}}
>
{interpolated[key].handler}
</div>
)}
</div>
}
</TransitionMotion>
);
}
});
module.exports = RouteTransition;
@luandro
Copy link

luandro commented Sep 10, 2015

Usage?

@abelovic
Copy link

Yes please... an example would be greatly appreciated! I have been searching for a solution to do page transitions with flow-router in meteor but the pattern should be the same regardless of router. The ultimate goal would be to use react-motion as the engine to do advanced page animations such as those in google material design. Has anyone had success with this?

@sompylasar
Copy link

Shouldn't the functions passed into TransitionSpring be bound to the RouteTransition instance?

        endValue={this.getEndValue}
        willEnter={this.willEnter}
        willLeave={this.willLeave}
        endValue={this.getEndValue.bind(this)}
        willEnter={this.willEnter.bind(this)}
        willLeave={this.willLeave.bind(this)}

@stevoland
Copy link

@sompylasar When using React.createClass methods are autobound to the instance

@miracle2k
Copy link

Usage example here: chenglou/react-motion#130

@maisano
Copy link
Author

maisano commented Sep 30, 2015

oops, sorry all. didn't see these comments until now.
the usage listed by @miracle2k is correct.

@silouanwright
Copy link

Note: this.props.location.pathname is what you'll want to pass if you're using newer version of React-Router

@silouanwright
Copy link

I don't suppose there is a way to get around setting position absolute on this thing is there? I have a react app in the middle of a header & footer... but because I have to use absolute positioning, the footer goes underneath all the routes.

@Madumo
Copy link

Madumo commented Dec 3, 2015

Same example but using a stateless functional component:

import React from 'react';
import {TransitionMotion, spring} from 'react-motion';

const willEnter = children => ({children, opacity: spring(0), scale: spring(0.95)});
const willLeave = (key, {children}) => ({children, opacity: spring(0), scale: spring(0.95)});
const getStyles = (children, pathname) => ({[pathname]: {children, opacity: spring(1), scale: spring(1)}});

export default function RouteTransition({children, pathname}) {
  return (
    <TransitionMotion
      styles={getStyles(children, pathname)}
      willEnter={willEnter}
      willLeave={willLeave}
    >
      {interpolated =>
        <div>
          {Object.keys(interpolated).map(key =>
            <div
              key={`${key}-transition`}
              style={{
                position: 'absolute',
                opacity: interpolated[key].opacity,
                transform: `scale(${interpolated[key].scale})`
              }}
            >
              {interpolated[key].children}
            </div>
          )}
        </div>
      }
    </TransitionMotion>
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment