inspired by react-motiom & react-router-v4 & react-motion-router
why react-motion ?
React-motion is a library that provides easing functions, which can be seen here.
The TransitionMotion API for React-Motion reads:
Helps you to do mounting and unmounting animation.
Here, TransitionMotion is combined with the React-Router to animate the route.
TransitionMotion
Start with TransitionMotion parameters:
TransitionStyle: {key:, data:? , style: }
-
DefaultStyles Initial style, which will be ignored in subsequent rendering.
-
Styles (prevInterpolatedStyles=> Array) The prevInterpolatedStyles parameter is undefined for the first rendering without defaultStyles. An array containing target values [{key:, style:, data:?}]. The key and style are required here, and the key is important because the TransitionMotion tracks the configuration of the render target based on this key. Styles is a collection of transitionstyles.
-
WillLeave: (styleThatLeft: TransitionStyle) =>? StyleThatLeft comes from the styles array passed in, and is uniquely identified by key. If this key was present in the previous render and is not present now, it will trigger the willLeave event when the animation is finished. If you return null, you want the TransitionStyle to disappear immediately.
-
willEnter: (styleThatEntered: TransitionStyle) => State when PlainStyle is about to enter. StyleThatEntered is similar to willLeave. It is triggered when the key was not present in the final render, but now it is. That means it’s time to go into animation. Note that PlainStyle is returned, which does not include the Spring () function.
-
didLeave: (styleThatLeft: {key: string, data? : any}) => void removes styleThatLeft when the animation is finally finished.
react-router
We implement the route and swith animation components, noting that in order to listen for routes, we need to pass in location.
The realization of the TransitionModel
We encapsulate a TransitionModel component and use it to encapsulate our route and swith.
First, the TransitionModel should eventually return a TransitionMotion.
<TransitionMotion
defaultStyles={this.getDefaultStyles()}
styles={this.getStyles()}
willEnter={this.willEnter}
willLeave={this.willLeave}
didLeave={this.didLeave}
>
{this.renderRoutes}
<\/TransitionMotion>Copy the code
The main willEnter, willLeave, didLeave functions are ultimately used to return a state of what the animation should be when it enters or exits, which we give the caller control over (passed in via props).
willEnter = () => this.props.willEnter
willLeave = () => ensureSpring(this.props.willLeave)
didLeave = (styleThatLeft) => this.props.didLeave && this.props.didLeave(styleThatLeft)Copy the code
Finally, the
component we need can be put in as a child component, using the createElement, cloneElement method.
renderRoute = (config) => { const props = { style: this.props.mapStyles(config.style), key: config.key } return this.props.wrapperComponent ! == false ? createElement(this.props.wrapperComponent, props, config.data) : cloneElement(config.data, props); } renderRoutes = interpolatedStyles => ( <div className={this.props.className}> { interpolatedStyles.map(this.renderRoute) } <\/div> )Copy the code
TransitionRoute
const getKey = ({pathname}, exact, path) => { return matchPath(pathname, {exact, path}) ? 'match' : 'no-match'; } export const TransitionRoute = ({component, exact, path, ... rest}) => { return ( <Route render={({location, match}) => ( <TransitionModel {... rest}> <Route key = {getKey(location, exact, path)} path = {path} exact = {exact} component = {component} location = {location} /> </TransitionModel> )} /> ) }Copy the code
Location is passed so that it can listen for route changes, not blocks, and key, as noted earlier, is the final TransitionStyle identifier.
There is only one child, so we can use matchPath to configure matching and mismatching keys. If math.random () is used instead of the key, we can’t trace the animation.
TransitionSwitch
To make things a little more complicated, we can use the children method of Route.
const SwitchWrapper = (props) => { return ( <Route children={({location})=>( <TransitionSwitch location={location} {... props} \/> )} /> ) }Copy the code
Because multiple Route at the bottom of the Switch components at the time of Switch, can get to nextProps. Through componentWillReceiveProps location, we can through this method to bind a key each child components, and then realize the animation, The code will not be posted, the end will give github address.
The effect
Route:
Switch: