react-transition-group
react-transition-group
react-transition-group solves the hardest problem in React UI transitions: animating components as they mount and unmount. It exposes four components, each solving a different patterns.
terminal
INSTALL
npm install react-transition-group
1 <Transition>: Lifecycle States
The base component. Exposes four states: entering, entered, exiting, exited. You write the CSS or JS logic yourself.
FadeTransition.js
import { Transition } from 'react-transition-group'; const duration = 300; const defaultStyle = { transition: `opacity ${duration}ms ease`, opacity: 0, }; const transitionStyles = { entering: { opacity: 1 }, entered: { opacity: 1 }, exiting: { opacity: 0 }, exited: { opacity: 0 }, }; export function FadeTransition({ in: inProp, children }) { return ( <Transition in={inProp} timeout={duration} unmountOnExit {/* removes from DOM after exit */} > {state => ( <div style={{ ...defaultStyle, ...transitionStyles[state] }}> {children} </div> )} </Transition> ); }
2 <CSSTransition>: Class-Based (Most Common)
The most frequently used component. Automatically adds/removes CSS class names at each lifecycle stage. You just write the CSS.
Modal.jsx
JSX
import { CSSTransition } from 'react-transition-group'; import './Modal.css'; export function Modal({ isOpen, onClose, children }) { return ( <CSSTransition in={isOpen} timeout={350} classNames="modal" {/* prefix for CSS classes */} unmountOnExit > <div className="modal-overlay" onClick={onClose}> <div className="modal-content" onClick={e => e.stopPropagation()} > {children} </div> </div> </CSSTransition> ); }
Modal.css
CSS
/* CSSTransition automatically adds these classes: */ /* .modal-enter, .modal-enter-active, .modal-enter-done */ /* .modal-exit, .modal-exit-active, .modal-exit-done */ .modal-enter .modal-content { opacity: 0; transform: scale(0.9) translateY(-20px); } .modal-enter-active .modal-content { opacity: 1; transform: scale(1) translateY(0); transition: all 350ms cubic-bezier(0.34, 1.56, 0.64, 1); } .modal-exit .modal-content { opacity: 1; transform: scale(1); } .modal-exit-active .modal-content { opacity: 0; transform: scale(0.9); transition: all 300ms ease; } .modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: grid; place-items: center; }
3 <SwitchTransition>: Mode-Controlled Swap
For swapping between two components (e.g. route changes, tab switches). Supports out-in (exit first, then enter) and in-out modes.
TabSwitcher.jsx
JSX
import { SwitchTransition, CSSTransition } from 'react-transition-group'; export function TabSwitcher({ activeTab }) { return ( <SwitchTransition mode="out-in"> <CSSTransition key={activeTab} {/* key change triggers transition */} timeout={200} classNames="tab" > <div className="tab-content"> {renderTab(activeTab)} </div> </CSSTransition> </SwitchTransition> ); }
4 <TransitionGroup>: List Animations
Wraps a list of CSSTransition components and manages adding/removing items with transitions automatically.
AnimatedList.jsx
JSX
import { TransitionGroup, CSSTransition } from 'react-transition-group'; export function AnimatedList({ items }) { return ( <TransitionGroup component="ul"> {items.map(item => ( <CSSTransition key={item.id} timeout={400} classNames="list-item" > <li>{item.text}</li> </CSSTransition> ))} </TransitionGroup> ); } /* CSS */ /* .list-item-enter { opacity: 0; transform: translateX(-20px); } .list-item-enter-active { opacity: 1; transform: translateX(0); transition: all 400ms ease; } .list-item-exit { opacity: 1; transform: translateX(0); } .list-item-exit-active { opacity: 0; transform: translateX(20px); transition: all 300ms ease; } */
