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.
- 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>
- 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
Use HTML Tag Names, Classes or Ids in CSS
Text Field Not Working in Safari
Calc() Function Inside Another Calc() in CSS
Bootstrap 4 Responsive Button Size
Bootstrap 4 Ie 11 Does Not Work
Arrow Before and After a Box with CSS
Using Fractional Em's in CSS's Font-Size Property
Ie Background Size Not Working
How Do CSS Sprites Speed Up a Web Site
How to Make a Transparent Border with CSS
Elastic Easing in CSS3, Best Approach
CSS Box-Shadow on Three Sides of a Div
Vertical Scrollbar Leads to Horizontal Scrollbar
Css3 Appearance Property for Ie
Linking to CSS Files from React Index
How to Draw an Incomplete Circle with CSS and in It How to Put a Picture