If we use CSS animation effect, we always have elements related to style on browser. The animiation may be pretty fine though.
Sure, we can figure out this with showing component according to ternary condition. But in the perspective of whole animation process, there may be some unexpected side effect because our component will be removed instantly according to condition.
To manage this problem, we can use third-party package.
npm install react-transition-group --save
1.Transition
import Transition from "react-transition-group/Transition";
Wrap component with 'Transition'
<Transition in={this.state.showBlock} timeout={300}>
{(state) => <p>{state}</p>}
</Transition>
In the 'in' prop, when this.state.showBlock is true, div will be rendered.(It is kind of condition.)
Inside of Transition component, you can use state variable which has four state (entering , entered, exiting, exited).
The process is really simple.
1. exited -> entering -> entered
2. entered -> exiting -> exited
You can check this from the line {(state) => <p>{state}</p>}
Here is more realistic example
<Transition
in={this.state.showBlock}
timeout={300}
mountOnEnter
unmountOnExit
>
{(state) => {
return (
<div
style={{
backgroundColor: "red",
width: 100,
height: 100,
margin: "auto",
transition: "opacity 0.3s ease-out",
opacity: state === "exiting" ? 0 : 1,
}}
></div>
);
}}
</Transition>
'mountOnEnter' props makes wrapped component shown only when 'in' prop has true.
'unmountOnExit' works exactly in an opposite way.
Finally, you can use state to apply animation into your element.
If you wanna give different timing with entering and exiting, you can set timing object with reserved property
const dynamicTiming = {
enter: 400,
exit: 1000,
};
const modal = (props) => {
return (
<Transition
in={props.show}
timeout={dynamicTiming}
mountOnEnter
unmountOnExit
>
...some code
</Transition>
Here are more props for 'Transition'
<Transition
in={props.show}
timeout={dynamicTiming}
mountOnEnter
unmountOnExit
onEnter={() => console.log("onEnter")}
onEntering={() => console.log("onEntering")}
onEntered={() => console.log("onEntered")}
onExit={() => console.log("onExit")}
onExiting={() => console.log("onExiting")}
onExited={() => console.log("onExited")}
>
with onSomeTiming event, you can control every step of transition.
The order of execution is :
onEnter -> onEntering -> onEntered
onExit -> onExiting -> onExited
import CSSTransition from "react-transition-group/CSSTransition";
return (
<CSSTransition
in={props.show}
timeout={dynamicTiming}
mountOnEnter
unmountOnExit
classNames="fade-slide"
>
<div className="Modal">
<h1>A Modal</h1>
<button className="Button" onClick={props.closed}>
Dismiss
</button>
</div>
</CSSTransition>
);
};
There is no state function anymore. Instead, we can use 'classNames' prop.
This classNames will add extended className during transition process.
For example,
fade-slide -> fade-slide-enter(start) -> fade-slide-enter-active(entering) -> fade-slide(entered)
The exiting process is similar.
Your role is just add this classes in your css file.
.fade-slide-enter {
}
.fade-slide-enter-active {
animation: openModal 0.4s ease-out forwards;
}
.fade-slide-exit {
}
.fade-slide-exit-active {
animation: closeModal 1s ease-out forwards;
}
Keep in mind that 'enter' and 'exit' style will be removed instantly according to your modal state. If you want to keep animation, give it to active classes.
On the other hand, you also can customize these css classes trunk.
<CSSTransition
in={props.show}
timeout={dynamicTiming}
mountOnEnter
unmountOnExit
classNames={{
enter: "",
enterActive: "ModalOpen",
exit: "",
exitActive: "ModalClosed",
}}
>
You also can use 'appear' and 'appearActive' property for when your component is mounted on the browser at the first time.
This can be used for animating kind of list items
TransitionGroup