React animate transition between components

后端 未结 3 1821
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-08 11:48

I\'d like to animate between two components where the first component fades out and is removed from the DOM before the next component is added to the DOM and fades in. Other

相关标签:
3条回答
  • 2020-12-08 12:06

    If you want to delay the rendering of the next component, you could use something like this:

    import React, { Component } from 'react';
    
    export default class DelayedRender extends Component {
    
        static propTypes = {
            delay: React.PropTypes.number.isRequired,
            children: React.PropTypes.element,
            className: React.PropTypes.string
        };
    
        constructor(props) {
            super(props);
    
            this.state = {
                render: false
            };
        }
    
        componentDidMount() {
            setTimeout(() => {
                const delayedClassNames = this.refs.noDelayed.className;
                this.setState({
                    render: true,
                    classNames: delayedClassNames
                });
            }, this.props.delay);
        }
    
        render() {
            const { children, className } = this.props;
            return this.state.render ?
                <div className={this.state.classNames}>{children}</div> :
                <div className={className} ref="noDelayed" ></div>;
        }
    }
    

    And in your render method:

    const ROUTE_TRANSITION_TIME = 500;
    const views = [];
    
    if (shouldRenderDelayedRoute) {
        views.push(
            <DelayedRender delay={ROUTE_TRANSITION_TIME} key="book">
                <A ref="book"/>
            </DelayedRender>
        );
    } else {
        views.push(<B key="library"/>);
    } 
    
    <ReactCSSTransitionGroup
       transitionEnterTimeout={ROUTE_TRANSITION_TIME}
       transitionLeaveTimeout={ROUTE_TRANSITION_TIME}
       transitionName="fade-transition"
                            >
        {views}
    </ReactCSSTransitionGroup>
    
    0 讨论(0)
  • 2020-12-08 12:11

    Solved using the componentWillUnmount() lifecycle method.

    http://jsfiddle.net/phepyezx/9/

    Here's the code:

    var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    
    const Off = React.createClass({
        componentWillUnmount () {
            this.props.handleTransitionEnd();
        },
        render()  {
            return (
                <div className="off button">OFF</div>
            )
        }
    });
    
    const On = React.createClass({
        componentWillUnmount () {
            this.props.handleTransitionEnd();
        },
        render()  {
            return (
                <div className="on button">ON</div>
            )
        }
    });
    
    var Switch = React.createClass({
        getInitialState: function() {
            return {
                on: false,
                transitionEnd: true
            };
        },
    
        toggle: function(e) {
            this.setState({
                on: !this.state.on,
                transitionEnd: false
            });
        },
    
        handleTransitionEnd() {
            this.setState({transitionEnd: true});
        },
    
        renderOff() {
            if (! this.state.on && this.state.transitionEnd) {
                return (
                    <Off key="off" handleTransitionEnd={this.handleTransitionEnd} />
                )
            }
        },
    
        renderOn() {
            if (this.state.on && this.state.transitionEnd) {
                return (
                    <On key="on" handleTransitionEnd={this.handleTransitionEnd} />
                )
            }
        },
    
        render: function() {
            return (
                <div>
                  <button onClick={this.toggle}>Toggle</button>
                  <ReactCSSTransitionGroup transitionName="switch">
                    {this.renderOff()}
                    {this.renderOn()}
                  </ReactCSSTransitionGroup>
                </div>
            );         
        }
    });
    
    React.render(<Switch/>, document.getElementById("switch"));
    

    And the relevant css:

    .switch-enter {
        opacity: 0.01;
    }
    .switch-enter.switch-enter-active {
        opacity: 1.0;
        transition: opacity 500ms ease-in;
    }
    .switch-leave {
        opacity: 1.0;
    }
    .switch-leave.switch-leave-active {
        opacity: 0;
        transition: opacity 500ms ease-out;
    }
    

    You can achieve the same effective result with Jonny Buchanan's answer which uses absolute positioning and a delay instead of componentWillUnmount()

    0 讨论(0)
  • 2020-12-08 12:14

    Another solution is to make the incoming and outgoing elements take up the same space, for example by having them both absolutely positioned:

    <ReactCSSTransitionGroup
        className="container"
        component="div"
        transitionName="switch">
    ...
    
    .container {
        position: relative;
    }
    .container > div {
        position: absolute;
    }
    

    http://jsfiddle.net/phepyezx/7/


    You can use transition-delay to wait until the leaving component disappears before making the entering component appear, e.g.:

    .fade-enter {
      opacity: 0.01;
    }
    .fade-enter.fade-enter-active {
      opacity: 1;
      transition: opacity 1s;
      transition-delay: 1s;
    }
    
    .fade-leave {
      opacity: 1;
    }
    .fade-leave.fade-leave-active {
      opacity: 0.01;
      transition: opacity 1s;
    }
    
    0 讨论(0)
提交回复
热议问题