React Lifecycle Motion
rc-motion is a React library designed to provide granular control over component entry, exit, and update animations by leveraging React's lifecycle methods. It enables developers to integrate CSS transition classes or custom JavaScript animation callbacks to manage the visual state of components as they appear, enter, leave, or disappear from the DOM. The package, at version 2.9.5, offers a robust set of features for orchestrating complex animation sequences and serves as a foundational component within the Ant Design ecosystem. Its API, centered around properties like `motionName`, `visible`, and comprehensive lifecycle callbacks (`onAppearStart`, `onEnterEnd`, etc.), emphasizes precise control over animation flow. However, developers should be aware that this specific package (`rc-motion`) has been superseded by `@rc-component/motion` (v1.x), which represents its actively maintained and developed successor.
Common errors
-
ReferenceError: CSSMotion is not defined
cause Incorrect import statement for the CSSMotion component.fixUse a named import: `import { CSSMotion } from 'rc-motion';` -
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
cause A functional component passed as a child to CSSMotion is attempting to receive a ref directly.fixWrap the child functional component with `React.forwardRef` to allow it to correctly receive and forward refs. -
Element persists in the DOM after its leave animation finishes, even if it's no longer visible.
cause The `removeOnLeave` prop is not enabled, or a bug in older versions prevents proper cleanup.fixSet the `removeOnLeave` prop on `CSSMotion` to `true`. If the issue persists with `rc-motion@2.9.5`, consider migrating to `@rc-component/motion`. -
TypeError: Cannot read properties of undefined (reading 'className') (or 'style')
cause The render prop function for `CSSMotion` is not correctly destructuring and passing the `className` or `style` props to the rendered element.fixEnsure your render prop looks like `{({ className, style }) => <div className={className} style={style} />}` to correctly apply the motion styles.
Warnings
- breaking The `rc-motion` package has been renamed and its active development moved to `@rc-component/motion`. While `rc-motion@2.9.5` is still available, new features and bug fixes are primarily released under the `@rc-component/motion` namespace (v1.x and above).
- deprecated The `rc-motion` package itself is considered deprecated. Its last major update (v2.9.5) was over two years ago. For actively maintained code, developers should transition to `@rc-component/motion`.
- gotcha Older versions of `rc-motion` (before fixes in `@rc-component/motion` v1.1.6) might exhibit 'DOM residue' where elements are not correctly removed from the DOM after leave animations, especially on re-activation or rapid toggling.
- gotcha Issues with ref forwarding to children wrapped by `CSSMotion` have been observed and fixed in later versions of `@rc-component/motion`. If you pass a ref directly to a functional child component within `CSSMotion`, it might not work as expected.
Install
-
npm install rc-motion -
yarn add rc-motion -
pnpm add rc-motion
Imports
- CSSMotion
import CSSMotion from 'rc-motion';
import { CSSMotion } from 'rc-motion'; - CSSMotionList
const CSSMotionList = require('rc-motion').CSSMotionList;import { CSSMotionList } from 'rc-motion'; - CSSMotionProps
import { CSSMotionProps } from 'rc-motion';import type { CSSMotionProps } from 'rc-motion';
Quickstart
import React, { useState } from 'react';
import { CSSMotion } from 'rc-motion';
function MyAnimatedComponent() {
const [visible, setVisible] = useState(true);
return (
<div>
<button onClick={() => setVisible(prev => !prev)}>
Toggle Motion
</button>
<CSSMotion
visible={visible}
motionName="my-fade"
onAppearStart={() => console.log('Appear Start')}
onAppearActive={() => console.log('Appear Active')}
onAppearEnd={() => console.log('Appear End')}
onEnterStart={() => console.log('Enter Start')}
onEnterActive={() => console.log('Enter Active')}
onEnterEnd={() => console.log('Enter End')}
onLeaveStart={() => console.log('Leave Start')}
onLeaveActive={() => console.log('Leave Active')}
onLeaveEnd={() => console.log('Leave End')}
removeOnLeave={true}
>
{({ className, style }) => (
<div
className={className}
style={{ ...style, padding: '20px', border: '1px solid blue', backgroundColor: 'lightblue' }}
>
Hello, Motion!
</div>
)}
</CSSMotion>
</div>
);
}
export default MyAnimatedComponent;