React Transition State
React-Transition-State is a lightweight, zero-dependency library providing a Hook-based API for managing component transition states in React applications. Its primary function is to facilitate CSS-driven animations and transitions by exposing a state machine that tracks a component's lifecycle through various transition phases (e.g., `preEnter`, `entering`, `entered`, `exiting`, `exited`). The library helps in seamlessly mounting and unmounting components from the DOM based on their transition status. The current stable version is 2.3.3, actively maintained with recent updates addressing SSR hydration and supporting modern React versions. It stands out for its minimal bundle size (~1KB post-treeshaking) and efficient single-render state transitions, offering a controlled alternative to libraries like `React Transition Group` without using derived state, which helps prevent common animation-related bugs.
Common errors
-
TypeError: (0 , react_transition_state__WEBPACK_IMPORTED_MODULE_1__.useTransition) is not a function
cause Attempting to import and use the deprecated `useTransition` hook after upgrading to v2.2.0 or newer.fixReplace `useTransition` with `useTransitionState` in your imports and usage. -
Property 'status' does not exist on type 'string'.
cause Using TypeScript with `react-transition-state` v2.0.0+ while still expecting the hook to return a string status, instead of the new object format.fixDestructure the returned object to access `status` and `isMounted`: `const [{ status, isMounted }, toggle] = useTransitionState(...)`. -
Error: Hydration failed because the initial UI does not match what was rendered on the server.
cause Server-Side Rendering (SSR) timing inconsistencies, specifically with `setTimeout` calls, in versions prior to v2.3.3.fixUpgrade `react-transition-state` to version 2.3.3 or higher. If using custom `setTimeout` logic, ensure it's handled correctly in both client and server environments.
Warnings
- breaking The `useTransition` hook was renamed to `useTransitionState` in v2.2.0 to avoid naming conflicts with React's native `useTransition` hook. The old `useTransition` export is deprecated.
- breaking The return value of `useTransition` (now `useTransitionState`) changed from a string representing the transition status to an object containing `status` and `isMounted` properties.
- gotcha Older versions of `react-transition-state` might experience Server-Side Rendering (SSR) hydration issues, potentially leading to client-side mismatches or errors.
- gotcha When using `styled-components` or similar CSS-in-JS libraries, ensure you pass the `status` prop correctly and handle its absence if the component is unmounted. `unmountOnExit` is crucial for removing the component from the DOM.
Install
-
npm install react-transition-state -
yarn add react-transition-state -
pnpm add react-transition-state
Imports
- useTransitionState
const { useTransitionState } = require('react-transition-state');import { useTransitionState } from 'react-transition-state'; - useTransitionMap
import useTransitionMap from 'react-transition-state';
import { useTransitionMap } from 'react-transition-state'; - useTransition
import { useTransition } from 'react-transition-state';
Quickstart
import React from 'react';
import { useTransitionState } from 'react-transition-state';
function Example() {
const [state, toggle] = useTransitionState({
timeout: 750,
preEnter: true,
unmountOnExit: true // Ensure component unmounts after exit transition
});
return (
<div>
{!state.isMounted && (
<button onClick={() => toggle(true)}>Show Message</button>
)}
{state.isMounted && (
<div className={`example ${state.status}`}>
<h2>React Transition State Demo</h2>
<p>This element will animate in and out of view.</p>
<p>Current status: <code>{state.status}</code></p>
<button onClick={() => toggle(false)}>Hide Message</button>
</div>
)}
</div>
);
}
export default Example;
/* Corresponding CSS for this example (not part of code block):
.example {
transition: all 0.75s ease-in-out;
}
.example.preEnter,
.example.exiting {
opacity: 0;
transform: scale(0.5);
}
.example.exited {
display: none;
}*/