Choreography
useTimeline
Play, reverse, stop and reset animations from events, without re-rendering.
Strx.useTimeline creates a controller for animations that should run from an event, such as a button press or a completed payment, instead of on mount. Components register as targets with strxId, and the controller drives their Reanimated values directly: no React state, no re-render.
1import { Strx } from "react-native-strx";23function SuccessCard() {4 const timeline = Strx.useTimeline({5 playback: "stagger",6 interval: 80,7 playables: [8 { target: "coin", animate: "scale-in from:opacity-0 duration-280 delay-300" },9 { target: "title", animate: "fade-in from:translate-y-12 duration-260" },10 { target: "button", animate: "fade-in from:translate-y-12 duration-240" },11 ],12 onComplete: () => console.log("done"),13 });1415 return (16 <>17 <Strx.View strxId="coin" style={styles.coin} />18 <Strx.Text strxId="title">Transfer complete</Strx.Text>19 <Strx.Pressable strxId="button" onPress={timeline.play}>20 <Strx.Text>Play again</Strx.Text>21 </Strx.Pressable>22 </>23 );24}Setup
The hook needs a target registry above it: Strx.Provider includes one, or use Strx.TimelineRoot on its own. Targets must be inside the same root.
<Strx.Provider>
<SuccessCard />
</Strx.Provider>Options
| Option | Type | Default | Meaning |
|---|---|---|---|
playables | { target: string; animate: AnimateProp }[] | — | What to play. target matches a component's strxId. animate takes anything the animate prop takes. |
playback | "parallel""serial""stagger" | "parallel" | How targets are scheduled |
interval | number | 100 | Offset between targets in ms, for stagger |
playCount | number"infinite" | — | How many times each target plays. "infinite" loops until stop(). |
onComplete | () => void | — | Called once when every target of a finite play() or reverse() has finished |
Scheduling works like Strx.Timeline: serial waits for each target's delay and duration, and stagger adds earlier targets' delay-* values to later offsets.
Controller
| Method | Behavior |
|---|---|
play() | Plays every target from its from frame to its to frame. |
reverse() | Plays back toward from. If a target is currently showing this timeline's animation, it reverses from its current position; otherwise it plays the full to → from pass. |
stop() | Cancels pending starts and freezes running animations where they are. |
reset() | Immediately returns every target to its from frame. |
reverse() uses the same schedule, interval and play count as play(). You can pass the methods straight to onPress.
The timeline recompiles when the playables array changes identity. Define it outside the component, or wrap it in useMemo, so it isn't rebuilt on every render.
onComplete
onComplete fires from the real end of the animations, once per run, after the last target finishes. It is not called:
- for
playCount="infinite", - after
stop()orreset(), - when a newer
play()orreverse()replaces the run.
That makes it safe for navigation or follow-up work:
1const timeline = Strx.useTimeline({2 playables: [{ target: "sheet", animate: "from:translate-y-400 to:translate-y-0 spring" }],3 onComplete: () => navigation.goBack(),4});56<Button title="Close" onPress={timeline.reverse} />;Targets
- Any STRX component, or a custom component, can be a target via
strxId. - A target may also have its own
animate. Its mount animation and the timeline's animation are separate; the timeline takes over when it plays. strxIdvalues must be unique within a root. A duplicate replaces the earlier target and warns in development; unmounting one of them doesn't unregister the other.- If
play()finds no component for atarget, it skips it and warns in development: "Timeline target was not registered. Check strxId." exit:tokens in a playable are ignored by the timeline.
Timeline vs. useTimeline
Strx.Timeline | Strx.useTimeline | |
|---|---|---|
Runs | When the children mount | When you call play() / reverse() |
Targets | Direct children | Any component with a matching strxId under the same root |
Controls | — | play, reverse, stop, reset, onComplete |
Re-renders | Render-time | None; drives shared values directly |