Skip to content

react-transition-group ​

这个库主要用于在 React 应用中管理组件的进入和离开动画。让我们从基础开始,逐步深入。

react-transition-group 主要包含四个组件:

  • Transition
  • CSSTransition
  • SwitchTransition
  • TransitionGroup

Transition ​

这是最基本的组件,它不使用 CSS 类,而是暴露了不同的状态作为函数参数。

在这个例子中,Transition 组件接受一个 in prop,用来控制是否显示内容。timeout 定义了过渡的持续时间。

js
import { Transition } from 'react-transition-group';
import React, { useState } from 'react';

const duration = 300;

const defaultStyle = {
  transition: `opacity ${duration}ms ease-in-out`,
  opacity: 0,
}

const transitionStyles = {
  entering: { opacity: 1 },
  entered:  { opacity: 1 },
  exiting:  { opacity: 0 },
  exited:  { opacity: 0 },
};

function App() {
  const [inProp, setInProp] = useState(false);
  
  return (
    <div>
      <Transition in={inProp} timeout={duration}>
        {state => (
          <div style={{
            ...defaultStyle,
            ...transitionStyles[state]
          }}>
            I'm a fade Transition!
          </div>
        )}
      </Transition>
      <button onClick={() => setInProp(!inProp)}>
        Click to Toggle
      </button>
    </div>
  );
}

CSSTransition ​

这个组件在 Transition 的基础上增加了 CSS 类的支持,使得使用 CSS 来定义过渡效果变得更加容易。

例子:根据 activeIndex 切换内容

js
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import React, { useState } from 'react';
import './styles.css';

function App() {
  const [activeIndex, setActiveIndex] = useState(1);

  const items = [
    { id: 1, text: "Content A" },
    { id: 2, text: "Content B" },
  ];

  return (
    <div>
      <TransitionGroup>
        <CSSTransition
          key={activeIndex}
          timeout={300}
          classNames="fade"
        >
          <div>
            {items.find(item => item.id === activeIndex).text}
          </div>
        </CSSTransition>
      </TransitionGroup>
      <button onClick={() => setActiveIndex(activeIndex === 1 ? 2 : 1)}>
        Toggle Content
      </button>
    </div>
  );
}

对应的CSS:

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

在这个例子中,当 activeIndex 改变时,CSSTransition 会自动应用相应的 CSS 类来实现淡入淡出效果。

CssTransition中重要的API解析

  • in: 控制组件显示和隐藏。
  • timeout: 涉及显示和隐藏的时间。{exit:300,enter:500} 表示退出和进入的时间。
  • classNames: 定义 CSS 类的前缀。注意是 classNames而不是className。
  • unmountOnExit: 是否在组件退出时卸载组件。true表示在退出时卸载组件。false表示在保持退出时的状态。

SwitchTransition ​

这个组件用于在两个组件之间进行过渡。

这个例子展示了如何在两个状态之间平滑切换。

js
import { SwitchTransition, CSSTransition } from 'react-transition-group';
import React, { useState } from 'react';
import './styles.css';

function App() {
  const [state, setState] = useState(false);
  
  return (
    <SwitchTransition>
      <CSSTransition
        key={state ? "Goodbye, world!" : "Hello, world!"}
        addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
        classNames='fade'
      >
        <button onClick={() => setState(state => !state)}>
          {state ? "Goodbye, world!" : "Hello, world!"}
        </button>
      </CSSTransition>
    </SwitchTransition>
  );
}

TransitionGroup ​

这个组件用于管理一组过渡组件,通常用于列表。

js
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import React, { useState } from 'react';
import './styles.css';

function App() {
  const [items, setItems] = useState([
    { id: 1, text: 'Buy milk' },
    { id: 2, text: 'Walk the dog' },
    { id: 3, text: 'Do laundry' }
  ]);

  const addItem = () => {
    setItems([...items, { id: items.length + 1, text: `New Task ${items.length + 1}` }]);
  };

  const removeItem = id => {
    setItems(items.filter(item => item.id !== id));
  };

  return (
    <div>
      <button onClick={addItem}>Add Item</button>
      <TransitionGroup>
        {items.map(({ id, text }) => (
          <CSSTransition
            key={id}
            timeout={500}
            classNames="item"
          >
            <div>
              {text}
              <button onClick={() => removeItem(id)}>X</button>
            </div>
          </CSSTransition>
        ))}
      </TransitionGroup>
    </div>
  );
}

对应的CSS:

css
.item-enter {
  opacity: 0;
}
.item-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}
.item-exit {
  opacity: 1;
}
.item-exit-active {
  opacity: 0;
  transition: opacity 500ms ease-in;
}

这个例子展示了如何为列表项添加进入和离开动画。

原理解释 ​

react-transition-group 的工作原理是在组件的生命周期中插入额外的状态。例如,对于 CSSTransition:

当组件进入时,它会经历 'enter' → 'enter-active' → 'enter-done' 状态。 当组件离开时,它会经历 'exit' → 'exit-active' → 'exit-done' 状态。 这些状态会被添加为 CSS 类,你可以为这些类定义样式来控制过渡效果。

通过这种方式,react-transition-group 提供了一个声明式的 API 来处理 React 组件的动画,使得添加复杂的进入和离开动画变得简单。