Each driver returns an animation you can start(), stop() or reset(), and combinators nest them: sequence() runs children in turn, parallel() together (stopping all if one stops, unless stopTogether: false), stagger() a fixed delay apart, delay() waits, and loop() repeats. A "New this week" screen fades in a title, pauses, then lets six cards follow 100 ms apart:
const fadeTo = (v: Animated.Value, toValue: number, duration = 300) =>
Animated.timing(v, { toValue, duration, useNativeDriver: true });
// ...inside Compose, with one Animated.Value per card (listeners log each reaching 1):
Animated.sequence([
fadeTo(title, 1), // 1. the title fades in
Animated.delay(200), // 2. a pause
Animated.stagger(100, cards.map((v) => fadeTo(v, 1))), // 3. cards, 100 ms apart
]).start(({ finished }) => log('sequence finished:', finished));Output
LOG +608ms title in LOG +1236ms card 1 in ... LOG +1881ms card 6 in LOG +1904ms sequence finished: true
On paper the cards finish at 800, 900 ... 1300 ms; the log runs late and bunches because native values report back asynchronously, and this emulator was busy. Chain follow-up work on the composition's start() callback, never on listeners.