CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-transition-group

A react component toolset for managing animations

Pending
Overview
Eval results
Files

replace-transition.mddocs/

Replace Transitions

The ReplaceTransition component is a specialized transition component that animates between exactly two children. It provides a controlled way to switch between two specific components with proper transition timing.

Capabilities

ReplaceTransition Component

Animates between two children based on the in prop value, using TransitionGroup internally for coordination.

/**
 * Specialized transition component that animates between exactly two children
 * @param props - ReplaceTransition props
 * @returns JSX element managing two-child transitions
 */
function ReplaceTransition({
  in: inProp,
  children,
  onEnter,
  onEntering,
  onEntered,
  onExit,
  onExiting,
  onExited,
  ...otherProps
}): JSX.Element;

interface ReplaceTransitionProps {
  /** Controls which child is shown (true = first child, false = second child) */
  in: boolean;
  /** Must be exactly two transition components (Transition or CSSTransition) */
  children: [React.ReactElement, React.ReactElement];
  /** Callback fired before the "entering" status is applied */
  onEnter?: (node?: HTMLElement) => void;
  /** Callback fired after the "entering" status is applied */
  onEntering?: (node?: HTMLElement) => void;
  /** Callback fired after the "entered" status is applied */
  onEntered?: (node?: HTMLElement) => void;
  /** Callback fired before the "exiting" status is applied */
  onExit?: (node?: HTMLElement) => void;
  /** Callback fired after the "exiting" status is applied */
  onExiting?: (node?: HTMLElement) => void;
  /** Callback fired after the "exited" status is applied */
  onExited?: (node?: HTMLElement) => void;
}

Usage Examples:

import React, { useState } from 'react';
import { ReplaceTransition, CSSTransition } from 'react-transition-group';
import './replace.css';

function ReplaceExample() {
  const [showFirst, setShowFirst] = useState(true);
  
  return (
    <div>
      <ReplaceTransition in={showFirst}>
        <CSSTransition
          timeout={300}
          classNames="fade"
          key="first"
        >
          <div className="content first">
            First Content
          </div>
        </CSSTransition>
        
        <CSSTransition
          timeout={300}
          classNames="fade"
          key="second"
        >
          <div className="content second">
            Second Content
          </div>
        </CSSTransition>
      </ReplaceTransition>
      
      <button onClick={() => setShowFirst(!showFirst)}>
        Switch Content
      </button>
    </div>
  );
}

// Image slider with replace transitions
function ImageSlider() {
  const [currentIndex, setCurrentIndex] = useState(0);
  const images = [
    { src: 'image1.jpg', alt: 'First image' },
    { src: 'image2.jpg', alt: 'Second image' }
  ];
  
  return (
    <div className="slider">
      <ReplaceTransition in={currentIndex === 0}>
        <CSSTransition
          timeout={500}
          classNames="slide"
          key="image1"
        >
          <img 
            src={images[0].src} 
            alt={images[0].alt}
            className="slider-image"
          />
        </CSSTransition>
        
        <CSSTransition
          timeout={500}
          classNames="slide"
          key="image2"
        >
          <img 
            src={images[1].src} 
            alt={images[1].alt}
            className="slider-image"
          />
        </CSSTransition>
      </ReplaceTransition>
      
      <button 
        onClick={() => setCurrentIndex(currentIndex === 0 ? 1 : 0)}
      >
        Next Image
      </button>
    </div>
  );
}

Component Behavior

ReplaceTransition automatically:

  1. Manages two children: Always expects exactly two child components
  2. Controls visibility: Shows first child when in={true}, second child when in={false}
  3. Handles transitions: Uses TransitionGroup internally to coordinate enter/exit timing
  4. Forwards callbacks: Passes lifecycle callbacks to the appropriate child component

Children Requirements

ReplaceTransition requires exactly two children:

// ✅ Correct - exactly two children
<ReplaceTransition in={showFirst}>
  <CSSTransition timeout={200} classNames="fade" key="first">
    <div>First</div>
  </CSSTransition>
  <CSSTransition timeout={200} classNames="fade" key="second">
    <div>Second</div>
  </CSSTransition>
</ReplaceTransition>

// ❌ Incorrect - wrong number of children
<ReplaceTransition in={showFirst}>
  <CSSTransition timeout={200} classNames="fade">
    <div>Only one child</div>
  </CSSTransition>
</ReplaceTransition>

Lifecycle Callback Flow

ReplaceTransition maps its lifecycle callbacks to the child components in a specific way:

  • When transitioning to first child (in={true}):

    • ReplaceTransition's onEnter, onEntering, onEntered map to first child's corresponding callbacks
    • First child transitions in normally
  • When transitioning to second child (in={false}):

    • ReplaceTransition's onEnter, onEntering, onEntered map to second child's onEnter, onEntering, onEntered callbacks
    • Second child transitions in (confusingly named, but this is how the source maps callbacks)
function CallbackExample() {
  const [active, setActive] = useState(true);
  
  return (
    <ReplaceTransition 
      in={active}
      onEnter={() => console.log('Child entering')}
      onExit={() => console.log('Child exiting')}
    >
      <CSSTransition
        timeout={200}
        classNames="first"
        key="first"
        onEntered={() => console.log('First child entered')}
      >
        <div>First</div>
      </CSSTransition>
      
      <CSSTransition
        timeout={200}
        classNames="second"
        key="second"
        onEntered={() => console.log('Second child entered')}
      >
        <div>Second</div>
      </CSSTransition>
    </ReplaceTransition>
  );
}

Example CSS for Replace Transitions

/* Fade transition */
.fade-enter {
  opacity: 0;
}

.fade-enter-active {
  opacity: 1;
  transition: opacity 300ms ease-in-out;
}

.fade-exit {
  opacity: 1;
}

.fade-exit-active {
  opacity: 0;
  transition: opacity 300ms ease-in-out;
}

/* Slide transition for image replacement */
.slide-enter {
  transform: translateX(100%);
}

.slide-enter-active {
  transform: translateX(0);
  transition: transform 500ms ease-out;
}

.slide-exit {
  transform: translateX(0);
}

.slide-exit-active {
  transform: translateX(-100%);
  transition: transform 500ms ease-in;
}

/* Cross-fade transition */
.crossfade-enter {
  opacity: 0;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.crossfade-enter-active {
  opacity: 1;
  transition: opacity 400ms ease-in-out;
}

.crossfade-exit {
  opacity: 1;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.crossfade-exit-active {
  opacity: 0;
  transition: opacity 400ms ease-in-out;
}

Use Cases

ReplaceTransition is ideal for:

  • Binary state switches: Toggle between two distinct states
  • Before/after comparisons: Show two versions of content
  • Image comparisons: Switch between two images with transition
  • Form steps: Navigate between two specific form sections
  • Content previews: Switch between edit and preview modes

For more complex switching scenarios with multiple options, consider using SwitchTransition instead.

Install with Tessl CLI

npx tessl i tessl/npm-react-transition-group

docs

css-transition.md

index.md

replace-transition.md

switch-transition.md

transition-group.md

transition.md

tile.json