useTransition
useTransition and <Transition> are deprecated. Use
usePresenceList for lists and
usePresence for a single element shown by a
boolean. See migrating below.
This hook is best suited for animating in & out datasets or items you don't particularly want to be left in the DOM, e.g. a dialog.
Usage
useTransition depends on an array of data. That data can be anything you want, we
use a lot of internals to track each datum including inferring the keys, this is the
first argument. The second is a config object, which is different to
useSpring or useSprings so take note!
With a function & deps
import { useTransition, animated } from '@react-spring/web'
function MyComponent({ data = [1, 2, 3] }) {
const [transitions, api] = useTransition(data, () => ({
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 1 },
}))
return transitions((style, item) => (
<animated.div style={style}>{item}</animated.div>
))
}
With a config object
import { useTransition, animated } from '@react-spring/web'
function MyComponent({ data = [1, 2, 3] }) {
const transitions = useTransition(data, {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 1 },
})
return transitions((style, item) => (
<animated.div style={style}>{item}</animated.div>
))
}
Transition function
The transition function takes a render function as an argument. This is how we append keys.
From the example above you can see we pass a style argument to the function, this style object
relates to the state of the animation, e.g. if the animation is ENTERING then the we use the
keys from the enter property of of your config object. For a deeper dive into the function
signature see the Typescript section.
Reference
Item is defined a lot below, it's automatically inferred from what you pass as the
content of the array you pass as the first argument to the hook. Therefore, if you
passed [1, 2, 3] then Item would be number.
| Prop | Type | Default |
|---|---|---|
from | object | function | – |
initial | object | function | – |
enter | object | object[] | function | – |
update | object | object[] | function | – |
leave | object | object[] | function | – |
keys | Array<string | number> | function | null | – |
sort | function | – |
trail | number | 0 |
reverse | boolean | false |
exitBeforeEnter | boolean | false |
expires | boolean | number | function | true |
ref | SpringRef | – |
config | object | function | object |
events | function | – |
Typescript
function useTransition<Item extends any>(
data: Item[],
configuration: ConfigObject
): TransitionFn<Item>
function useTransition<Item extends any>(
data: Item[],
configurationFn: () => ConfigObject
deps?: any[]
): [transition: TransitionFn<Item>, api: SpringRef]
type TransitionFn = (
style: SpringValues,
item: Item,
transitionState: TransitionState<Item>,
index: number
) => ReactNode
Where ConfigObject is described above
TS Glossary
Migrating to usePresenceList
Instead of a render function, usePresenceList returns an array of entries.
Map over it and pass each entry's key to the element you render.
// before
const transitions = useTransition(items, {
keys: item => item.id,
exitBeforeEnter: true,
...props,
})
return transitions((style, item) => (
<animated.div style={style}>{item.text}</animated.div>
))
// after
const entries = usePresenceList(items, {
keys: item => item.id,
mode: 'wait',
...props,
})
return entries.map(({ key, item, springs }) => (
<animated.div key={key} style={springs}>
{item.text}
</animated.div>
))
The extra render function arguments are on the entry, or come from .map:
// before
transitions((style, item, t, index) => (
<animated.div style={{ ...style, zIndex: index }}>{t.phase}</animated.div>
))
// after
entries.map(({ key, springs, phase }, index) => (
<animated.div key={key} style={{ ...springs, zIndex: index }}>
{phase}
</animated.div>
))
<Transition> has no component replacement. Call usePresenceList with the
same props instead:
// before
;<Transition items={items} from={from} enter={enter} leave={leave}>
{(style, item) => <animated.div style={style}>{item}</animated.div>}
</Transition>
// after
const entries = usePresenceList(items, { from, enter, leave })
return entries.map(({ key, item, springs }) => (
<animated.div key={key} style={springs}>
{item}
</animated.div>
))
If you pass a boolean, use usePresence instead:
// before
const transitions = useTransition(isOpen, props)
return transitions((style, isOpen) =>
isOpen ? <animated.div style={style} /> : null
)
// after
const presence = usePresence(isOpen, props)
return presence && <animated.div style={presence.springs} />
Other differences:
exitBeforeEnter: truebecomesmode: 'wait', which also works with lists.- Move
config: (item, index, phase) => ...intoenter,updateorleave. A top-levelconfigfunction receives the spring key. - A top-level
delayfunction receives the spring key, not the item key. Move item-specific delays into the phase. - Use
keys; the singularkeyalias is not supported. depsonly hold backupdate. Items still enter and leave whendatachanges anddepsdo not.expiresonly accepts a boolean.onDestroyedand a top-levelonResolveare not accepted.onResolveinside a phase still works.
Examples
The examples have moved to usePresenceList.