
Security News
Deno 2.6 + Socket: Supply Chain Defense In Your CLI
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.
react-motion
Advanced tools
import {Motion, spring} from 'react-motion';
// In your render...
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
{value => <div>{value.x}</div>}
</Motion>
Animate a counter from 0 10. For more advanced usage, see below.
Npm:
npm install react-motion
Bower:
bower install react-motion
1998 Script Tag:
<script src="path/to/react-motion/build/react-motion.js"></script>
(Module exposed as ReactMotion)
Or build it yourself from the repo: git clone https://github.com/chenglou/react-motion.git && cd react-motion && npm install && npm run prerelease
For React-native, instead of require('react-motion'), do require('react-motion/native').
(P.S. Don't forget to compile for production when you test your animation's performance!)
For 95% of use-cases of animating components, we don't have to resort to using hard-coded easing curves and duration. Set up a stiffness and damping for your UI element, and let the magic of physics take care of the rest. This way, you don't have to worry about petty situations such as interrupted animation behavior. It also greatly simplifies the API.
This library also provides an alternative, more powerful API for React's TransitionGroup.
The library exports Motion, StaggeredMotion, TransitionMotion, presets, spring and utils.
spring: number -> ?[stiffness, damping] -> ConfigurationObject(Note: not the Spring component in version <0.3.0.)
The pervasive helper used to specify the how to animate to the destination value, e.g. spring(10, [120, 17]) returns an opaque configuration that describes "an animation to the value 10, with a physics spring's stiffness of 120 and damping of 17". spring(10) without the spring configuration array defaults to [170, 26]. See below for more usage and see here for a list of convenient configurations the library exports.
Props:
defaultStyle: ?ObjectOptional. The value when the component first renders (ignored in subsequent renders). Accepts an object of arbitrary keys, mapping to initial values you want to animate, e.g. {x: 0, y: 10}.
style: ObjectRequired. Must have the same keys throughout component's existence. Must have the same keys as defaultStyle (if provided). Similar to defaultStyle, but asks for a spring configuration as the destination value: {x: spring(10), y: spring(20, [120, 17])}.
If a plain number is provided rather than a spring config, instead of giving an interpolated value in the children function param below, we'll jump straight to that number value.
children: Object -> ?ReactElementRequired function, which is passed an interpolated style object, e.g. {x: 5.2, y: 12.1}. Must returns a React element to render.
<Motion defaultStyle={{x: 0}} style={{x: spring(10, [120, 17])}}>
{interpolatedStyle => <div>{interpolatedStyle.x}</div>}
</Motion>
When you want to animate a list of items, you can certainly create an array of Motions and animate each. However, you often want to "stagger" them, i.e. animate items in one after another with a delay. Hard-coding this duration goes against the very purpose of spring physics. Instead, here's a natural, physics-based alternative, where "the destination position of an item depends on the current position of another".
defaultStyles: ?Array<Object>Optional. Similar to Motion's defaultStyle, except an array of styles.
styles: ?Array<Object> -> Array<Object>Required function. Takes as argument the previous array of styles (which is undefined at first render, unless defaultStyles is provided!). Return the array of styles containing the destination values.
children: Array<Object> -> ?ReactElementA required function. Similar to Motion's children, but accepts the array of interpolated styles instead, e.g. [{x: 5}, {x: 6.4}, {x: 8.1}]
<StaggeredMotion
defaultStyles={[{x: 0}, {x: 10}, {x: 20}]}
styles={prevStyles => prevStyles.map((_, i) => {
return i === 0
? {x: spring(this.state.mouseX)} // first item follows mouse's x position
: prevStyles[i - 1]; // item i follow the position of the item before it, creating a natural staggering spring
})}>
{interpolatedStyles =>
<div>
{interpolatedStyles.map((style, i) =>
<div key={i} style={{left: style.x}} />
)}
</div>
}
</StaggeredMotion>
The magic component that helps you to do mounting and unmounting animation. Unlike React's TransitionGroup, instead of retaining a few items in a list when they disappear, TransitionMotion diffs on the shape of its styles object prop.
The general idea
Let TransitionMotion's styles be {myKey1: {x: spring(30)}, myKey2: {x: spring(20)}}. The interpolated styles passed to the children function, after a moment, would be {myKey1: {x: 15.1}, myKey2: {x: 8.2}}.
A few renders later, you kill myKey1 and its style config, i.e. pass the new styles as {myKey2: {x: spring(20)}}. TransitionMotion detects a missing key, but retains the key in the interpolated values as {myKey1: ..., myKey2: ...}.
This is when TransitionMotion calls the prop willLeave that you provide, passing myKey2 as argument. You're asked to return a final style config (for example, {x: spring(50)}) for myKey1, representing the style values that, when interpolatedStyles.myKey1 reaches them, allows TransitionMotion to truly kill myKey1 and its style config from the interpolated styles.
In summary: styles is {k1: {x: spring(30)}, k2: {x: spring(20)}}. Next render, styles is {k2: {x: spring(20)}}. The interpolated styles passed to children aren't affected, but remember that the k2: configReturnedFromWillLeave (say, {x: spring(50)}) part doesn't exist in the actual styles anymore. Moments later, interpolated styles reach {k1: {x: 50}, k2: {x: 19.2}}; it then re-renders, kills k1 and become {k2: {x: 19.2}}. All this time, you're mapping over the interpolate styles and rendering two items, until the last render.
Similar but simpler logic for willEnter.
defaultStyles: ?Object<string, Object>Optional. Accepts an object of the format {myKey1: styleObject, myKey2: styleObject} where each styleObject is similar to Motion's defaultStyle. The keys must be unique non-number IDs (number keys in JS object screws with keys enumeration order, which is important when you map over it in children function).
styles: Object | (?Object -> Object)Required. Accepts an object similar to defaultStyles, but where styleObject has spring configurations: {myKey1: {x: spring(10)}, myKey2: {y: spring(20)}}. Alternatively, also accepts a function which takes a prevStyles parameter (just like StaggeredMotion; you can do staggered unmounting animation!), and returns the destination styles.
willEnter: (string, Object, Object, Object, Object) -> ObjectNot a very helpful type definition...
Optional. Pass a function that takes the arguments (keyFromStylesThatJustEntered, correspondingStyleOfKey, styles, currentInterpolatedStyle, currentSpeed), and that returns a style object similar to a defaultStyle.
Defaults to a function that returns correspondingStyleOfKey, in this case {x: spring(20)}.
willLeave: (string, Object, Object, Object, Object) -> ObjectOptional. Pass a function that takes the arguments keyThatJustLeft, correspondingStyleOfKey, styles, currentInterpolatedStyle, currentSpeed) and that return a style object containing some spring(...) as the destination configuration.
Optional, defaults to correspondingStyleOfKey, i.e. immediately killing the key from the interpolated values.
children: Object -> ?ReactElementA required function. Similar to Motion's children, but accepts the object of interpolated styles instead.
const Demo = React.createClass({
getInitialState() {
return {
blocks: {
a: 'I am a',
b: 'I am b',
c: 'I am c',
},
};
},
getStyles() {
let configs = {};
Object.keys(this.state.blocks).forEach(key => {
configs[key] = {
opacity: spring(1),
text: this.state.blocks[key], // not interpolated
};
});
return configs;
},
// not used here! We don't add any new item
willEnter(key) {
return {
opacity: spring(0), // start at 0, gradually expand
text: this.state.blocks[key], // this is really just carried around so
// that interpolated values can still access the text when the key is gone
// from actual `styles`
};
},
willLeave(key, style) {
return {
opacity: spring(0), // make opacity teach 0, after which we can kill the key
text: style.text,
};
},
handleClick(key) {
const {...newBlocks} = this.state.blocks;
delete newBlocks[key];
this.setState({blocks: newBlocks});
},
render() {
return (
<TransitionMotion
styles={this.getStyles()}
willEnter={this.willEnter}
willLeave={this.willLeave}>
{interpolatedStyles =>
<div>
{Object.keys(interpolatedStyles).map(key => {
const {text, ...style} = interpolatedStyles[key];
return (
<div onClick={this.handleClick.bind(null, key)} style={style}>
{text}
</div>
);
})}
</div>
}
</TransitionMotion>
);
},
});
presetsSome tasteful, commonly used spring presets you can plug into your style like so: {val: 10, config: presets.wobbly}. See here.
utilsSince TransitionMotion dictates styles to be an object, manipulating keys could be a little more tedious than manipulating arrays. Here are the common scenarios' solutions:
{newKey: myConfigForThisKey, ...oldConfigs}.{...oldConfigs, newKey: myConfigForThisKey}.utils.reorderKeys function.Note: object keys creation order is now guaranteed by the specs, except for integer keys, which follow ascending order and should not be used with TransitionMotion. Fortunately, you can just add a letter to your key to turn them into "true" strings.
reorderKeys: (Object, Function) -> Objectutils.reorderKeys({a: 1, b: 2}, (keysArray) => ['b', 'a']) // gives {b: 2, a: 1}
Function will receive, as arguments, the array of keys in Object and should return a new array of keys (with e.g. order changed and/or keys removed). reorderKeys will then return a new object of the same shape as object, but with the keys in the order Function dictated.
Hard-coded duration goes against fluid interfaces. If your animation is interrupted mid-way, you'd get a weird completion animation if you hard-coded the time. That being said, in the demo section there's a great Spring Parameters Chooser for you to have a feel of what spring is appropriate, rather than guessing a duration in the dark.
TransitionMotion container itself?You don't. Unless you put it in another TransitionMotion...
See StaggeredMotion
ref doesn't work in the children function.React string refs won't work:
<Motion style={...}>{currentValue => <div ref="stuff" />}</Motion>
This is how React works. Here's the callback ref solution.
0.3.0 (September 30th 2015)
react-spring is a spring-physics based animation library that is highly flexible and performant. It provides a more modern API compared to react-motion and supports hooks, making it a popular choice for new React projects.
framer-motion is a powerful animation library that offers a simple and declarative API for creating animations. It supports keyframes, spring animations, and gestures, and is known for its ease of use and rich feature set.
react-transition-group is a low-level animation library that provides more control over the animation lifecycle. It is often used for more complex animations where developers need fine-grained control over the transition states.
FAQs
A spring that solves your animation problems.
The npm package react-motion receives a total of 560,406 weekly downloads. As such, react-motion popularity was classified as popular.
We found that react-motion demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.

Security News
New DoS and source code exposure bugs in React Server Components and Next.js: what’s affected and how to update safely.

Security News
Socket CEO Feross Aboukhadijeh joins Software Engineering Daily to discuss modern software supply chain attacks and rising AI-driven security risks.