{"id":11893,"library":"react-transition-group","title":"React Transition Group","description":"React Transition Group is a set of low-level primitive components for managing component states over time, specifically designed to facilitate animations in React applications. It enables developers to define and control lifecycle events for components entering, exiting, or remaining in the DOM. The current stable version is 4.4.5, last updated in August 2022, with a release cadence focused on stability and compatibility with React's evolving ecosystem. This library doesn't dictate specific animation libraries or CSS frameworks; instead, it provides hooks and class toggles (`CSSTransition`) that allow integration with arbitrary CSS transitions/animations or JavaScript animation libraries. Its key differentiator is providing an unopinionated, foundational API for animation patterns, contrasting with higher-level animation libraries that often bundle their own animation engines or opinions.","status":"active","version":"4.4.5","language":"javascript","source_language":"en","source_url":"https://github.com/reactjs/react-transition-group","tags":["javascript","react","transition","addons","transition-group","animation","css","transitions"],"install":[{"cmd":"npm install react-transition-group","lang":"bash","label":"npm"},{"cmd":"yarn add react-transition-group","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-transition-group","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for React components.","package":"react","optional":false},{"reason":"Peer dependency for rendering React components to the DOM.","package":"react-dom","optional":false},{"reason":"TypeScript definitions for type safety.","package":"@types/react-transition-group","optional":true}],"imports":[{"note":"The core component for managing generic animation states. Use named import for modern ESM environments.","wrong":"const Transition = require('react-transition-group').Transition;","symbol":"Transition","correct":"import { Transition } from 'react-transition-group';"},{"note":"A utility component for CSS transitions, often used with `TransitionGroup`. Named import from the main package entry.","wrong":"import CSSTransition from 'react-transition-group/CSSTransition';","symbol":"CSSTransition","correct":"import { CSSTransition } from 'react-transition-group';"},{"note":"Used for animating a list of components entering or exiting. Requires named import.","wrong":"const TransitionGroup = require('react-transition-group');","symbol":"TransitionGroup","correct":"import { TransitionGroup } from 'react-transition-group';"},{"note":"Introduced in v4.2.0 for animating a single component replacing another. Requires named import.","symbol":"SwitchTransition","correct":"import { SwitchTransition } from 'react-transition-group';"}],"quickstart":{"code":"import React, { useState } from 'react';\nimport ReactDOM from 'react-dom/client';\nimport { CSSTransition, TransitionGroup } from 'react-transition-group';\n\n// Basic CSS for demonstration (e.g., in App.css or a style tag)\n/*\n.item-enter {\n  opacity: 0;\n}\n.item-enter-active {\n  opacity: 1;\n  transition: opacity 500ms ease-in;\n}\n.item-exit {\n  opacity: 1;\n}\n.item-exit-active {\n  opacity: 0;\n  transition: opacity 500ms ease-out;\n}\n*/\n\ninterface TodoItemProps {\n  todo: string;\n  onRemove: () => void;\n}\n\nconst TodoItem: React.FC<TodoItemProps> = ({ todo, onRemove }) => (\n  <div className=\"todo-item\" onClick={onRemove}>\n    {todo}\n  </div>\n);\n\nconst App: React.FC = () => {\n  const [todos, setTodos] = useState<string[]>([\"Learn React\", \"Build something\", \"Deploy it\"]);\n  const [newTodo, setNewTodo] = useState<string>('');\n  const nextId = React.useRef(todos.length);\n\n  const handleAddTodo = () => {\n    if (newTodo.trim() === '') return;\n    setTodos([...todos, newTodo.trim()]);\n    setNewTodo('');\n    nextId.current++;\n  };\n\n  const handleRemoveTodo = (indexToRemove: number) => {\n    setTodos(todos.filter((_, index) => index !== indexToRemove));\n  };\n\n  return (\n    <div>\n      <h1>Animated Todo List</h1>\n      <input\n        type=\"text\"\n        value={newTodo}\n        onChange={(e) => setNewTodo(e.target.value)}\n        onKeyDown={(e) => e.key === 'Enter' && handleAddTodo()}\n        placeholder=\"Add a new todo\"\n      />\n      <button onClick={handleAddTodo}>Add Todo</button>\n      <TransitionGroup component=\"ul\" style={{ listStyle: 'none', padding: 0 }}>\n        {todos.map((todo, index) => (\n          <CSSTransition\n            key={todo + index} // Using todo + index for a unique key, though real apps might use a stable ID\n            timeout={500}\n            classNames=\"item\"\n            nodeRef={React.createRef<HTMLLIElement>()} // Required for Strict Mode and React 18+\n          >\n            {(state) => (\n              <li ref={state.nodeRef} style={{marginBottom: '5px'}}>\n                <TodoItem todo={todo} onRemove={() => handleRemoveTodo(index)} />\n              </li>\n            )}\n          </CSSTransition>\n        ))}\n      </TransitionGroup>\n    </div>\n  );\n};\n\nconst root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);\nroot.render(\n  <React.StrictMode>\n    <App />\n  </React.StrictMode>\n);\n","lang":"typescript","description":"This quickstart demonstrates animating a list of items entering and exiting using `TransitionGroup` and `CSSTransition`, applying basic CSS classes for fade effects. It also addresses the `nodeRef` requirement for React Strict Mode."},"warnings":[{"fix":"Refer to the official migration guide from v1 to v2+ at reactcommunity.org/react-transition-group/Migration.md. This often involves changes to component structure and prop names.","message":"The API for `react-transition-group` version 2 and above is not backward compatible with the original `react-addons-transition-group` (v1). Significant changes were made to the component structure and prop requirements. Code written for v1 will not work with v2+ without migration.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"For `CSSTransition` and `Transition` components, always provide a `nodeRef` prop, which is a `React.Ref` object pointing to the DOM element you want to transition. The child component must then forward this ref. For `CSSTransition` specifically, use a render prop pattern to access the `nodeRef` property provided by the component state.","message":"Using `react-transition-group` in React Strict Mode (or with React 18+) without the `nodeRef` prop will produce `findDOMNode is deprecated in StrictMode` warnings in the console. This is because `findDOMNode` is an internal mechanism previously used by the library.","severity":"gotcha","affected_versions":">=4.4.0"},{"fix":"Plan a migration to `react-transition-group` v4.x, carefully reviewing the breaking changes between v1 and v2, and subsequent versions.","message":"Version 1 of `react-transition-group` is no longer actively maintained. While still available, it's recommended to upgrade to the latest stable version for bug fixes, performance improvements, and compatibility with newer React features.","severity":"deprecated","affected_versions":"<2.0.0"},{"fix":"If your intention is to use CSS classes to drive animations, ensure you are using the `CSSTransition` component and providing appropriate `classNames` and `timeout` props. `Transition` is for more generic, often JavaScript-driven, animation logic.","message":"The `Transition` component provides basic lifecycle hooks and state management for animating. For applying CSS classes during transitions (e.g., `fade-enter`, `fade-enter-active`), you should use `CSSTransition`, which extends `Transition` specifically for this purpose.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Provide a `nodeRef={React.createRef<HTMLElement>()}` prop to your `CSSTransition` or `Transition` component, and ensure the direct child component forwards this ref to the DOM element being animated. For `CSSTransition`, use the render prop pattern to access `state.nodeRef`.","cause":"Using `CSSTransition` or `Transition` without explicitly passing a `nodeRef` prop in React Strict Mode or with React 18+.","error":"Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of CSSTransition which is inside StrictMode. Instead, add a ref directly to the element you want to reference."},{"fix":"Ensure `classNames` is either a string (e.g., `classNames=\"my-animation\"`) which will generate `my-animation-enter`, `my-animation-exit` etc., or an object specifying custom class names for each state (e.g., `{ enter: 'my-enter', exit: 'my-exit' }`).","cause":"Incorrectly configuring the `classNames` prop on `CSSTransition`, or forgetting to provide it altogether.","error":"The 'classNames' prop should be a string or a plain object. The 'classNames' prop must be provided to CSSTransition."},{"fix":"Ensure `TransitionGroup` is rendered with a valid DOM element as its `component` prop (e.g., `'div'`, `'ul'`). Alternatively, ensure all children of `TransitionGroup` are `CSSTransition` or `Transition` components, and that `nodeRef` is correctly implemented for each. For complex scenarios, consider using `mountOnEnter` and `unmountOnExit` to control DOM presence.","cause":"This can sometimes occur if `TransitionGroup` has `component={null}` and the immediate children are not handling their own DOM mounting/unmounting correctly, or if animations are trying to run on an already unmounted node.","error":"TypeError: Cannot read properties of undefined (reading 'appendChild') or similar DOM manipulation errors when unmounting."}],"ecosystem":"npm"}