Breaking Changes

This page is all about breaking changes between v8.x and v9.x. Get ready to upgrade!

The useTransition hook

The new useTransition is used like this:

// 1. Provide items and props
const transition = useTransition(items, props)
// 2. Map the items into a fragment
const fragment = transition((style, item) => {
// 3. Render each item
return <a.div style={style}>{item}</a.div>
})

The transition function

On this page, the transition function returned by useTransition is referred to as the TransitionFn (its type name in TypeScript).

It accepts a callback that receives four arguments: the animated values, the item, the Transition object, and the sibling position.

It returns a React fragment containing every element returned by your callback. As you might assume, elements in the middle of their leave animation need to remain mounted.

All elements in the fragment are guaranteed to have a key prop, whether or not you define one explicitly. Unkeyed elements will use the ctrl.id from their Transition object.

Transition objects

For every unique item key, there exists a Transition object. The only time you have access to a Transition object is when it's passed as the 3rd argument of your TransitionFn callback.

// The `t` argument is a Transition object.
// The `i` argument is the sibling position.
const elems = transition((style, item, t, i) => (
<a.div style={style}>{t.phase}</a.div>
))

Transition keys

Every Transition object has a unique key that identifies it. You have the option of defining explicit keys or letting the "item" (the value represented by the Transition object) be its own key.

To define explicit keys, you must define the keys prop in your useTransition props. For example, when using an items array, the new keys prop can be:

  • an array of keys
  • or a mapping function that returns a key for any item given to it.
useTransition(items, {
// Using a function
keys: item => item.key,
// Using an array created by lodash.map
keys: _.map(items, 'key'),
})

⚠️ You must use explicit keys for any item that is an immutable object.

Using explicit keys for mutable objects is unnecessary. 🥳

The key prop

If you're passing a single item to useTransition, you have the option of passing a single key as the key prop.

useTransition(item, {
key: item.key,
})

The expires prop

The expires prop lets you control when removed items are unmounted (after their leave animation has finished). By default, unmounting is postponed until the next render or until all transitions are resting.

When true or <= 0, the default behavior is used.

When false, items are never unmounted.

When > 0, this prop is used in a setTimeout call that forces a rerender if the component that called useTransition doesn't rerender on its own after an item's leave animation is finished.

Finally, the expires prop can be a function that receives an item and returns any of the values mentioned above.

The ref prop

Pass a ref as the ref prop for access to the ref API.

const ref = useRef()
useTransition(items, {
ref,
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
})
useEffect(() => {
ref.current.start()
})

The TransitionHandle object in ref.current has an almost identical API to what useSprings has.

The sort prop

The sort prop is a function that takes two items, returns -1 when the 1st item should appear first, and returns 1 when the 2nd item should.

It's a useful shortcut for slicing and sorting your items array before passing it to the useTransition hook.

// v8
useTransition(items.slice().sort(props.sort), null, props)
// v9
useTransition(items, {
sort: (a, b) => { ... },
...props
})

Other changes

Here are the breaking changes in useTransition without their own section.

  • The reset prop now prefers the initial prop over the from prop.

  • The unique prop was removed. Unique mode is now the default behavior.

  • The lazy prop was removed (in favor of the expires prop). Lazy mode is now the default behavior.

  • The onDestroyed prop was removed.

  • The order prop was removed.


The onFrame prop

This prop has been renamed to onChange, because it's not necessarily called from within a requestAnimationFrame callback.

For example, the onChange prop is called when you call the set method of an animated value.


The to prop

When using an async to function inside a component that renders frequently, you'll need to memoize your to function to prevent an unintended restart.

One solution is to use the useCallback hook.

useSpring({
to: useCallback(async animate => { ... }, []),
})

Another solution is to pass a props function.

useSpring(() => ({
to: async animate => { ... },
}))

The from prop

The from prop now behaves differently in imperative updates. When defined, it implies the reset prop is true. Previously, the from prop would not affect the animation unless reset: true was explicitly defined.

To prevent this behavior, you can define reset: false.

The example above uses the new SpringValue API.


The interpolate function

This function is now the to function.

import { to } from 'react-spring'
const { x, y } = useSpring({
from: { x: 0, y: 0 },
})
// Combine two animated values
to([x, y], (x, y) => x / y)

Globals API

Global configuration has been improved.

import { colorNames, createStringInterpolator } from './globals'
// v8
import * as Globals from 'react-spring/animated/Globals'
Globals.injectDefaultElement('div')
Globals.injectStringInterpolator(createStringInterpolator)
Globals.injectColorNames(colorNames)
// v9
import { Globals } from 'react-spring'
Globals.assign({
defaultElement: 'div',
createStringInterpolator,
colorNames,
})

The Controller class

Unless you've been using new Controller() or have been accessing the controllers property off the ref API, these changes won't affect you.

  • The interpolate method is now the to method.

  • The stop method no longer has an optional finished argument. Instead, it accepts zero or more keys to specifically stop animating.

  • The pause method was removed. This method will be restored once the pausing feature is ready.

  • The destroy method was renamed to dispose.

  • Most properties have been either renamed or removed.