Flow router and React page transition animations

Is there a simple way to do page transitions animations with Flow Router and React? I’ve been struggling with it for a couple of days.

My page has an admin style interface (side nav and top nav) so I’m not wanting to animate the change on the whole page, but instead apply the animation to the inner content.

If someone had an example that would be really helpful.

2 Likes

I did get to the bottom of this, if anyone’s interested let me know and I’ll post a code example tomorrow

2 Likes

Yep, could you post your code please. Would be nice to conclude your question.

1 Like

I’d also be interested in this. Meteoric made this too easy on mobile!

OK, here’s how we got it working (after many hours of pain!)

So the route looks as you’d expect:

FlowRouter.route("/addCustomer", {
    name: "addCustomer",
    action() {
        //console.log("route ", this.name);
        mount(Layout, {
            content: (<CustomerEditPageWrapper/>)
        });
    }
});

And then the Layout page looks like this

import React from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

const ContentContainer = React.createClass({
    render() {
        console.log("ContentContainer.render()", this.props.children);
        
        return (
            <div key="contentContainer">
                <ReactCSSTransitionGroup
                    component="div"
                    transitionName="example"
                    transitionEnterTimeout={300}
                    transitionLeaveTimeout={300}
                >
                    {React.cloneElement(this.props.children, {
                        key: this.props.children.key
                    })}
                </ReactCSSTransitionGroup>
            </div>
        );
    }
});

export const Layout = ({content}) => (
    <div id="app">
        <ContentContainer key="content">{content}</ContentContainer>
    </div >
);

And finally the CSS looks like this:

.example-enter {
    -webkit-transition: opacity 0.3s ease-in-out;
    transition: opacity 0.3s ease-in-out;
    opacity: 0;
    position: absolute;
}

.example-enter.example-enter-active {
    opacity: 1;
}

.example-leave {
    -webkit-transition: opacity 0.3s ease-in-out;
    transition: opacity 0.3s ease-in-out;
    opacity: 1;
    position: absolute;
}

.example-leave.example-leave-active {
    opacity: 0;
}

The above uses ReactCSSTransitionGroup from the React addons https://facebook.github.io/react/docs/animation.html, but the example itself is actually a reworking of the code from the animations example in the React Router repo: https://github.com/reactjs/react-router/blob/master/examples/animations/app.js.

The only bit I’ve had issues with is if your site CSS includes absolute positions it can stop transition appearing as a crossfade, with instead the first component fading out and the second one fading in. I haven’t worked out how to solve that, I’m not great with CSS.

4 Likes

Any idea how to do “slide in/slide out” transitions?

1 Like

I would second that question for slide in / outs.
Of course, any of those transitions would be awesome:
https://tympanus.net/Development/PageTransitions/

If anyone is using the class syntax for Layout, I figured out a simpler implementation - simply add the unique key to each mounting component when you are rendering it in the callback:

import React from 'react';
import {FlowRouter} from 'meteor/kadira:flow-router';
import {mount} from 'react-mounter';

import Layout from '../../ui/layouts/Layout.jsx';
import Home from '../../ui/pages/home/Home.jsx';
import About from '../../ui/pages/about/About.jsx';

FlowRouter.route('/', {
	name: 'home',
	action() {
		mount(Layout, {
			content: () => {
				return (<Home key="home" />);
			}
		});
	}
});

FlowRouter.route('/about', {
	name: 'about',
	action() {
		mount(Layout, {
			content: () => {
				return (<About key="about" />);
			}
		});
	}
});

And then in Layout you wrap <ReactCSSTransitionGroup> around your content call:

import React, {Component, PropTypes} from 'react';
import {FlowRouter} from 'meteor/kadira:flow-router';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

class Layout extends Component {
	render() {
		return (
			<div id="layout">
				<ReactCSSTransitionGroup
					className="transition"
					component="div"
					transitionName="example"
					transitionAppear={true}
					transitionAppearTimeout={300}
					transitionEnter={true}
					transitionEnterTimeout={300}
					transitionLeave={true}
					transitionLeaveTimeout={0}
				>
					{this.props.content()}
				</ReactCSSTransitionGroup>
            </div>
		);
	}
}

export default Layout;
1 Like