React Animate Transition Between Components

React animate transition between components

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()

ReactJS - Fade between 2 different components

You can use react-spring to animate your components, first

import { animated, useTransition } from "react-spring";

then inside your component

const [showLogin, set] = useState(false);

const toggle = () => {
set(!showLogin);
};

const transitions = useTransition(showLogin, null, {
from: { position: "absolute", opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 }
});

and then you will render your components, make sure to replace div with animated.div

<div className="login col-md-6 mt-5 mx-auto">
{transitions.map(({ item, key, props }) =>
item ? (
<LoginForm //animated.div
onLoginSubmit={onLoginSubmit}
email={email}
setEmail={setEmail}
password={password}
setPassword={setPassword}
showPasswordReset={showPasswordReset}
/>
) : (
<ForgotPasswordForm //animated.div
onPasswordResetSubmit={onPasswordResetSubmit}
setShowForgotPassword={toggle}
/>
)
)}
</div>

I made a simple example, you can check it out here

How can I animate between 2 states in React and see both states during transition

The problem is that during the transition you only see the current object in the leaving and the entering element. It is because you use the state instead the item property of the transition. Let the useTransition handle the state change, it knows which element leaves and which enters:

    {transitions.map(({ item, props, key }) => {
return (
<animated.div key={key} style={{ ...props, background: pages[item].background }}>
{pages[item].text}
</animated.div>
)
})}

The direction change is almost works as it is in the comment. Make sure the condition in the ternary operation match the direction value. For example if you set the direction to 1 and 0 (instead of 1 and -1) then your original condition should work.

  from: { opacity: 0, transform: `translate3d(${currentState.direction ? '200%': '-200%'},0,0)` },
enter: { opacity: 1, transform: 'translate3d(0%,0,0)' },
leave: { opacity: 0, transform: `translate3d(${currentState.direction ? '-200%': '200%'},0,0)` },

https://codesandbox.io/s/distracted-lamport-6pkup?file=/src/index.js

How can i switch between react components using framer motion?

A couple of things were missing from the above answer to get exit animations working.

  1. If you want exit animations to work within AnimationPresense you need to set keys on its children
        <AnimatePresence initial={false} custom={direction}>
{page === 0 && <TestComp key="0" bg="rgb(171, 135, 255)" />}
{page === 1 && <TestComp key="1" bg="rgb(68, 109, 246)" />}
{page === 2 && <TestComp key="2" bg="rgb(172, 236, 161)" />}
</AnimatePresence>

  1. If you want to animate something in while something is still animating out without having massive content shifting, you need to take them out of the flow. (use absolute positioning and wrap with relatively positioned container)
      <div style={{ position: "relative", height: "300px", width: "300px" }}>
<AnimatePresence initial={false} custom={direction}>
...
</AnimatePresence>
</div>

and on the child components

  height: 100%;
width: 100%;
position: absolute;

Working codesandbox: https://codesandbox.io/s/framer-motion-carousel-animation-wetrf?file=/src/App.tsx:658-708



Related Topics



Leave a reply



Submit