this repo has no description
1# react-native-reanimated
2
3### Create Smooth Animations with an Excellent Developer Experience
4
5#### Why Choose Reanimated?
6
7##### Declarative API
8
9Reanimated offers a declarative approach to creating animations, simplifying complexity from numerous methods down to just a few. Define the desired animation outcome and let Reanimated handle the style and property animations for you.
10
11##### High Performance
12
13With Reanimated, define animations in plain JavaScript that run natively on the UI thread by default. This ensures smooth interactions up to 120 fps or more, delivering a native experience users expect.
14
15##### Rich Features
16
17Reanimated's capabilities extend beyond animating simple views or images. Integrate your animations with device sensors or keyboards, utilize Layout Animations, and effortlessly animate elements between navigation screens.
18
19- **Learn More**: Discover the features of Reanimated 3 in our latest article.
20
21 - [See blog post](#)
22
23##### Animation Capabilities
24
25Animate every React Native prop on iOS, Android, and the Web up to 120 fps.
26
27```typescript
28function App() {
29 const width = useSharedValue(100);
30 const handlePress = () => {
31 width.value = withSpring(width.value + 50);
32 };
33 return <Animated.View style={{ ...styles.box, width }} />;
34}
35```
36
37##### Gesture Integration
38
39Experience smooth gestures through Reanimated's integration with React Native Gesture Handler.
40
41```typescript
42import { Gesture, GestureDetector } from "react-native-gesture-handler";
43
44function App() {
45 const pan = Gesture.Pan();
46
47 return (
48 <GestureDetector gesture={pan}>
49 <Animated.View />
50 </GestureDetector>
51 );
52}
53```
54
55##### Layout Animations
56
57Automatically animate views when they are added or removed from the view hierarchy.
58
59```typescript
60function App() {
61 return <Animated.View entering={FadeIn} exiting={FadeOut} />;
62}
63```
64
65##### Sensor-Based Animations
66
67Easily connect your animations to a gyroscope or accelerometer with just one hook.
68
69```typescript
70const gyroscope = useAnimatedSensor(SensorType.GYROSCOPE)
71
72useDerivedValue(() => {
73 const { x, y, z } = gyroscope.sensor.value
74})
75```
76
77##### Keyboard-Based Animations
78
79Create animations based on the device keyboard state and position.
80
81```typescript
82function App() {
83 const keyboard = useAnimatedKeyboard()
84 const animatedStyle = useAnimatedStyle(() => ({
85 transform: [{ translateY: -keyboard.height.value }],
86 }))
87 //...
88}
89```
90
91##### Shared Element Transitions
92
93Seamlessly animate elements between navigation screens with a single line of code.
94
95```typescript
96function App() {
97 return <Animated.View sharedTransitionTag="hero-element" />;
98}
99```
100
101#### Sponsors
102
103### We are Software Mansion
104
105React Native Core Contributors and experts in addressing all types of React Native issues. Whether you need assistance with gestures, animations, or general React Native development, we're here to help.
106
107## useAnimatedStyle
108
109`useAnimatedStyle` is a hook that allows you to create an animated styles object, similar to `StyleSheet`, which can be dynamically updated using shared values. These styles must be applied to the `style` property of an Animated component and are automatically refreshed when associated shared values or React state change.
110
111Unlike inline styling, `useAnimatedStyle` provides access to values stored in shared values within the defined style object. For animating properties directly on components, consider using `useAnimatedProps`.
112
113### Reference
114
115```typescript
116import { useAnimatedStyle } from 'react-native-reanimated';
117
118function App() {
119 const animatedStyles = useAnimatedStyle(() => ({
120 opacity: sv.value ? 1 : 0,
121 }));
122
123 return <Animated.View style={[styles.box, animatedStyles]} />;
124}
125```
126
127#### Arguments
128
129##### `updater`
130
131A function that returns an object containing the style properties you wish to animate. Any style property available in React Native can be animated.
132
133##### `dependencies` (Optional)
134
135An optional array of dependencies. This is only relevant when using Reanimated without its Babel plugin on the Web.
136
137### Returns
138
139The hook returns an animated style object, which should be assigned to the `style` property of an Animated component you wish to animate. The `updater` callback provides a value resembling a regular style object that can incorporate shared values.
140
141### Example
142
143#### Remarks
144
145- Animated styles override React Native's static styles. Values in animated styles take precedence over those from static styles.
146
147```typescript
148function App() {
149 const animatedStyles = useAnimatedStyle(() => ({
150 width: sv.value,
151 }));
152
153 return (
154 <Animated.View
155 style={[
156 animatedStyles, // ⚠️ overrides the static style width
157 { width: 100 },
158 ]}
159 />
160 );
161}
162```
163
164- The order of animated styles in a style array does not affect their application. The most recently updated animated style is applied.
165
166- Removing an animated style from a view does not revert values set by that style. To reset these values, explicitly set them to `undefined` within the animated style.
167
168- Modifying shared values inside the `useAnimatedStyle` callback can lead to undefined behavior and potential infinite loops.
169
170```typescript
171function App() {
172 const sv = useSharedValue(0)
173 const animatedStyles = useAnimatedStyle(() => {
174 sv.value = withTiming(1) // Avoid this!
175 return { opacity: sv.value }
176 })
177}
178```
179
180- Animated styles should only be applied to `Animated` components. Applying them to non-animated components will cause an error.
181
182- Define dynamic styles using `useAnimatedStyle`, while keeping static styles separate via the `StyleSheet` API or inline styles. This minimizes unnecessary style recalculations. Static and dynamic styles can be merged using array syntax:
183
184```typescript
185function App() {
186 const animatedStyles = useAnimatedStyle(() => ({
187 offset: sv.value,
188 }));
189
190 return <Animated.View style={[styles.box, animatedStyles]} />;
191}
192
193const styles = StyleSheet.create({
194 box: {
195 height: 120,
196 width: 120,
197 backgroundColor: '#b58df1',
198 },
199});
200```
201
202- Animated styles can be shared between components to reduce code duplication.
203
204- The callback for `useAnimatedStyle` executes on both the JavaScript and UI threads. To ensure thread-specific behavior, use the `global._WORKLET` variable:
205
206```typescript
207function App() {
208 const animatedStyles = useAnimatedStyle(() => {
209 if (global._WORKLET) {
210 // Code specific to the UI thread
211 } else {
212 // Fallback code for the JS thread
213 }
214 })
215}
216```
217
218### Platform Compatibility
219
220|Android|iOS|Web|
221|-|-|-|
222|✅|✅|✅|
223
224## Shared Element Transitions
225
226> **Caution:**\
227> Shared Element Transition is an experimental feature and not recommended for production use yet. Feedback is welcomed to enhance its implementation.
228
229Shared Element Transition enables a smooth transformation of a component from one screen to another.
230
231### Reference
232
233```typescript
234import Animated from 'react-native-reanimated';
235
236const Stack = createNativeStackNavigator();
237
238function One({ navigation }) {
239 return (
240 <>
241 <Animated.View sharedTransitionTag="sharedTag" />
242 <Button title="Two" onPress={() => navigation.navigate('Two')} />
243 </>
244 );
245}
246
247function Two({ navigation }) {
248 return (
249 <>
250 <Animated.View sharedTransitionTag="sharedTag" />
251 <Button title="One" onPress={() => navigation.navigate('One')} />
252 </>
253 );
254}
255
256export default function SharedElementExample() {
257 return (
258 <NavigationContainer>
259 <Stack.Navigator screenOptions={{ headerShown: true }}>
260 <Stack.Screen name="One" component={One} />
261 <Stack.Screen name="Two" component={Two} />
262 </Stack.Navigator>
263 </NavigationContainer>
264 );
265}
266```
267
268### Overview
269
270When Reanimated detects a component with a `sharedTransitionTag` being mounted or unmounted, it searches for the last registered view with the same tag. If two matching components are found, their styles are captured and both views are temporarily moved to a transition container during the animation. Afterward, they return to their original parent.
271
272Without custom animations, properties like `width`, `height`, `originX`, `originY`, and `transformMatrix` animate by default over 500ms using `withTiming`.
273
274### Implementation
275
276To create a shared transition between components on different screens, assign the same `sharedTransitionTag`. Unique tags are required for multiple shared views on the same screen.
277
278**Screen A**
279
280```typescript
281<View
282 sharedTransitionTag="sharedTag"
283 style={{ width: 150, height: 150, backgroundColor: 'green' }}
284/>
285```
286
287**Screen B**
288
289```typescript
290<View
291 sharedTransitionTag="sharedTag"
292 style={{ width: 100, height: 100, backgroundColor: 'green' }}
293/>
294```
295
296### Custom Animation
297
298Custom animations can be created using `SharedTransition.custom` for regular animations or `SharedTransition.progressAnimation` for progress-based ones.
299
300```typescript
301import { SharedTransition } from "react-native-reanimated"
302
303const transition = SharedTransition.custom((values) => {
304 "worklet"
305 return {
306 height: withSpring(values.targetHeight),
307 width: withSpring(values.targetWidth),
308 }
309})
310 .progressAnimation((values, progress) => {
311 "worklet"
312 const getValue = (
313 progress: number,
314 target: number,
315 current: number
316 ): number => {
317 return progress * (target - current) + current
318 }
319 return {
320 width: getValue(progress, values.targetWidth, values.currentWidth),
321 height: getValue(progress, values.targetHeight, values.currentHeight),
322 }
323 })
324 .defaultTransitionType(SharedTransitionType.ANIMATION)
325```
326
327By setting `defaultTransitionType(SharedTransitionType.ANIMATION)`, the custom animation is used for screen transitions, while progress-based animations apply during swipe-back gestures (iOS only). Use `defaultTransitionType(SharedTransitionType.PROGRESS_ANIMATION)` to apply progress-based animations in both scenarios.
328
329To use a custom animation, pass it as `sharedTransitionStyle` to components. Different animations can be assigned to different components sharing the same tag for directional transitions.
330
331```typescript
332<View
333 sharedTransitionTag="reanimatedTransition"
334 sharedTransitionStyle={transition}
335 style={{ backgroundColor: 'blue', width: 200, height: 100 }}
336/>
337```
338
339### Example
340
341Your browser does not support the video tag.
342
343Your browser does not support the video tag.
344
345Expand the full code:
346
347```typescript
348<Pressable onPress={() => goToDetails('countryside')}>
349 <Animated.View
350 sharedTransitionTag={'countryside'}
351 style={[
352 styles.imageOne,
353 { backgroundColor: gallery.countryside.color },
354 ]}
355 />
356</Pressable>
357<View style={styles.row}>
358 <Pressable onPress={() => goToDetails('florence')}>
359 <Animated.View
360 sharedTransitionTag={'florence'}
361 style={[
362 { width: width / 2 - 35 },
363 styles.imageTwo,
364 { backgroundColor: gallery.florence.color },
365 ]}
366 />
367 </Pressable>
368 <Pressable onPress={() => goToDetails('dawn')}>
369 <Animated.View
370 sharedTransitionTag={'dawn'}
371 style={[
372 { width: width / 2 - 35 },
373 styles.imageThree,
374 { backgroundColor: gallery.dawn.color },
375 ]}
376 />
377 </Pressable>
378</View>
379```
380
381### Remarks
382
383- Only the native stack is supported.
384- Animatable properties include `width`, `height`, `originX`, `originY`, and `transformMatrix`.
385- Layout for shared view children isn't computed during transitions.
386- Currently supports only the old React Native architecture (Paper).
387- Future support for the new React Native architecture (Fabric) is planned.
388
389### Platform Compatibility
390
391|Android|iOS|Web|
392|-|-|-|
393|✅|✅|❌|
394
395## Troubleshooting
396
397### Initialization Issues
398
399Reanimated consists of four core components that must align within the same minor version:
400
401- C++
402- Java
403- JavaScript
404- Reanimated Babel plugin.
405
406Discrepancies in these components, especially when transpiled with different versions of the Reanimated Babel plugin, can lead to undefined behavior and errors.
407
408#### Failed to Create a Worklet
409
410**Problem:** This typically occurs if Reanimated is not installed correctly, such as omitting the Reanimated Babel plugin from `babel.config.js`.
411
412**Solution:** Refer to the installation documentation at [Reanimated Getting Started](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin) for guidance.
413
414#### Native Part of Reanimated Doesn't Seem to Be Initialized
415
416**Problem:** This issue arises when the native side of Reanimated fails to initialize from JavaScript.
417
418**Solution:**
419
4201. Ensure your app is rebuilt after installing or upgrading Reanimated.
4211. Verify that your platform is supported by Reanimated, including:
422 - Android
423 - iOS
424 - macOS
425 - tvOS
426 - visionOS
427 - Web
4281. For brownfield apps, manually initialize the native library.
429
430#### Unknown Version of Reanimated Babel Plugin
431
432**Problem:** This occurs when the JavaScript side cannot retrieve the version of the Reanimated Babel plugin.
433
434**Solution:**
435
4361. Check if any part of your code is transpiled with an outdated version of the Reanimated Babel plugin.
4371. Ensure you are not using a release bundle with a debug build, as this is unsupported.
438
439#### Mismatch Between JavaScript Code Version and Reanimated Babel Plugin Version
440
441**Problem:** This can happen when code is transpiled with an outdated version of the Reanimated Babel plugin.
442
443**Solution:** Reset your Metro bundler cache using `yarn start --reset-cache`, `npm start -- --reset-cache`, or `expo start -c` and rerun the app. If issues persist, identify dependencies that may contain outdated worklets by examining error messages.
444
445#### Using Dev Bundle in a Release App Build is Not Supported
446
447**Problem:** This occurs when a release build uses a development JavaScript bundle.
448
449**Solution:** Refer to relevant documentation for more information.
450
451#### Couldn't Determine the Version of the Native Part of Reanimated
452
453**Problem:** This happens when Reanimated cannot determine its native part's version.
454
455**Solution:** Ensure your app is rebuilt after upgrading `react-native-reanimated`. For Expo Go users, use the exact version bundled with the Expo SDK.
456
457#### Mismatch Between JavaScript and Native Parts of Reanimated
458
459**Problem:** This occurs when different versions of the JavaScript and native parts are used.
460
461**Solution:** Confirm that your app is rebuilt post-upgrade. For Expo Go, ensure compatibility with the bundled version in the Expo SDK.
462
463#### C++ Side Failed to Resolve JavaScript Code Version
464
465See "Couldn't Determine the Version of the Native Part of Reanimated" and "Unknown Version of Reanimated Babel Plugin."
466
467#### Mismatch Between C++ Code Version and JavaScript Code Version
468
469Refer to issues regarding mismatches between JavaScript parts, native parts, and the Reanimated Babel plugin.
470
471#### C++ Side Failed to Resolve Java Code Version
472
473**Problem:** This occurs when the version of the Java part cannot be determined, likely due to a missed rebuild after an upgrade.
474
475**Solution:** Rebuild your app and check if the issue persists. If it does, consider reporting it on GitHub.
476
477#### Mismatch Between C++ Code Version and Java Code Version
478
479Refer to "Native Side Failed to Resolve Java Code Version."
480
481#### Java Side Failed to Resolve C++ Code Version
482
483**Problem:** This happens when the version of the C++ part cannot be determined, likely due to a missed rebuild after an upgrade.
484
485**Solution:** Refer to "Native Side Failed to Resolve Java Code Version."
486
487#### Mismatch Between Java Code Version and C++ Code Version
488
489Refer to "Native Side Failed to Resolve Java Code Version."
490
491#### Multiple Versions of Reanimated Were Detected
492
493**Problem:** This error occurs when more than one instance of Reanimated exists in your project, often due to dependencies installing it within their own `node_modules`.
494
495**Solution:**
496
497- For Yarn users, add a `resolutions` property in `package.json`:
498
499 ```json
500 "resolutions": {
501 "react-native-reanimated": "<Reanimated version>"
502 }
503 ```
504
505- For npm users, use the `overrides` property:
506
507 ```json
508 "overrides": {
509 "react-native-reanimated": "<Reanimated version>"
510 }
511 ```
512
513Afterward, run your package manager again (`yarn` or `npm install`).
514
515#### Another Instance of Reanimated Was Detected
516
517Refer to "Multiple Versions of Reanimated Were Detected."
518
519#### Outdated Version of React Native for New Architecture
520
521**Problem:** Reanimated supports the New Architecture (Fabric) only on the latest minor release of React Native.
522
523**Solution:** Upgrade to a newer version of React Native or downgrade Reanimated. Consult the compatibility table for supported versions.
524
525### Warnings
526
527#### Reduced Motion Setting is Enabled on This Device
528
529**Problem:** This warning helps avoid confusion when reduced motion is enabled.
530
531**Solution:** Ignore this warning in development mode as it's safe. To disable, add:
532
533```javascript
534LogBox.ignoreLogs([
535 "[Reanimated] Reduced motion setting is enabled on this device.",
536])
537```
538
539#### Tried to Modify Key of an Object Which Has Been Converted to a Shareable
540
541**Problem:** This warning indicates that a shared value should be used or objects in worklets accessed more granularly.
542
543##### 1. Not Using Shared Values
544
545Example:
546
547```javascript
548const obj = { prop: 1 }
549
550function worklet() {
551 "worklet"
552 console.log(obj.prop)
553}
554
555runOnUI(worklet)()
556obj.prop = 2 // Warning occurs here.
557runOnUI(worklet)()
558```
559
560**Solution:** Use a shared value instead:
561
562```typescript
563const sv = useSharedValue({ prop: 1 })
564
565function worklet() {
566 "worklet"
567 console.log(sv.value.prop)
568}
569
570runOnUI(worklet)()
571sv.value = { prop: 2 } // Correct usage.
572```
573
574##### 2. Not Accessing Object Properties Granularly
575
576Example:
577
578```javascript
579const obj = { propAccessedInWorklet: 1, propNotAccessedInWorklet: 2 }
580
581function worklet() {
582 "worklet"
583 console.log(obj.propAccessedInWorklet)
584}
585
586runOnUI(worklet)()
587obj.propNotAccessedInWorklet = 3 // Warning occurs here.
588```
589
590**Solution:** Assign accessed properties to variables beforehand:
591
592```typescript
593const obj = { propAccessedInWorklet: 1, propNotAccessedInWorklet: 2 }
594const propAccessedInWorklet = obj.propAccessedInWorklet
595
596function worklet() {
597 "worklet"
598 console.log(propAccessedInWorklet)
599}
600
601runOnUI(worklet)()
602obj.propNotAccessedInWorklet = 3 // Correct usage.
603```
604
605### Threading Issues
606
607#### Tried to Synchronously Call a Non-Worklet Function on the UI Thread
608
609**Problem:** This occurs when calling a non-worklet function from within a worklet.
610
611Example:
612
613```javascript
614function callee() {
615 console.log("hello")
616}
617
618function caller() {
619 "worklet"
620 callee() // Error here.
621}
622
623runOnUI(caller)()
624```
625
626**Solution:**
627
6281. Mark the function as a worklet using `worklet` directive:
629
630 ```typescript
631 function callee() {
632 "worklet"
633 console.log("hello")
634 }
635 ```
636
6371. Execute the function on the JS thread with `runOnJS`:
638
639 ```typescript
640 function caller() {
641 "worklet"
642 runOnJS(callee)()
643 }
644 ```
645
646For more information, refer to Reanimated's documentation on worklets.
647
648## useAnimatedScrollHandler
649
650The `useAnimatedScrollHandler` hook provides an event handler reference that can be utilized with React Native's scrollable components. This hook is part of the `react-native-reanimated` library.
651
652### Reference
653
654```typescript
655import { useAnimatedScrollHandler } from 'react-native-reanimated';
656
657function App() {
658 const offsetY = useSharedValue(0);
659
660 const scrollHandler = useAnimatedScrollHandler((event) => {
661 offsetY.value = event.contentOffset.y;
662 });
663
664 // ...
665
666 return <Animated.ScrollView onScroll={scrollHandler} />;
667}
668```
669
670#### Arguments
671
672##### `handlers`
673
674An object containing custom keys that correspond to native event names. Available keys include:
675
676- `onScroll`
677- `onBeginDrag`
678- `onEndDrag`
679- `onMomentumBegin`
680- `onMomentumEnd`
681
682Each key should map to an individual worklet function. These functions are triggered when the associated events occur on a connected Scrollable component.
683
684The event worklets receive two parameters:
685
686- `event`: An object containing information about the scroll. The structure of this payload varies based on the event type. Refer to React Native's ScrollView documentation for details.
687
688- `context`: A plain JavaScript object used for storing state that persists between scroll events. This allows communication between multiple event handlers when provided as an object of worklets.
689
690##### `dependencies` (Optional)
691
692An optional array of dependencies, relevant only when using Reanimated without the Babel plugin on the Web.
693
694#### Returns
695
696The hook returns a handler object suitable for integration with a scrollable container. The returned handler should be assigned to the `onScroll` parameter, regardless of whether it is configured to handle scroll, momentum, or drag events. For proper functionality, use containers wrapped with `Animated`, such as `Animated.ScrollView`.
697
698### Example
699
700### Remarks
701
702- The returned handler can be passed to multiple components. It will invoke for the specified events whenever any component dispatches them.
703- If a single worklet function of type `(event) => void` is provided instead of an object mapping functions to event keys, it is treated as a handler for the `onScroll` event.
704- Only the `onScroll` event is supported on Web.
705
706### Platform Compatibility
707
708|Android|iOS|Web|
709|-|-|-|
710|✅|✅|✅|
711
712## useAnimatedScrollHandler
713
714The `useAnimatedScrollHandler` hook provides an event handler reference that can be utilized with React Native's scrollable components. This hook is part of the `react-native-reanimated` library.
715
716### Reference
717
718```typescript
719import { useAnimatedScrollHandler } from 'react-native-reanimated';
720
721function App() {
722 const offsetY = useSharedValue(0);
723
724 const scrollHandler = useAnimatedScrollHandler((event) => {
725 offsetY.value = event.contentOffset.y;
726 });
727
728 // ...
729
730 return <Animated.ScrollView onScroll={scrollHandler} />;
731}
732```
733
734#### Arguments
735
736##### `handlers`
737
738An object containing custom keys that correspond to native event names. Available keys include:
739
740- `onScroll`
741- `onBeginDrag`
742- `onEndDrag`
743- `onMomentumBegin`
744- `onMomentumEnd`
745
746Each key should map to an individual worklet function. These functions are triggered when the associated events occur on a connected Scrollable component.
747
748The event worklets receive two parameters:
749
750- `event`: An object containing information about the scroll. The structure of this payload varies based on the event type. Refer to React Native's ScrollView documentation for details.
751
752- `context`: A plain JavaScript object used for storing state that persists between scroll events. This allows communication between multiple event handlers when provided as an object of worklets.
753
754##### `dependencies` (Optional)
755
756An optional array of dependencies, relevant only when using Reanimated without the Babel plugin on the Web.
757
758#### Returns
759
760The hook returns a handler object suitable for integration with a scrollable container. The returned handler should be assigned to the `onScroll` parameter, regardless of whether it is configured to handle scroll, momentum, or drag events. For proper functionality, use containers wrapped with `Animated`, such as `Animated.ScrollView`.
761
762### Example
763
764### Remarks
765
766- The returned handler can be passed to multiple components. It will invoke for the specified events whenever any component dispatches them.
767- If a single worklet function of type `(event) => void` is provided instead of an object mapping functions to event keys, it is treated as a handler for the `onScroll` event.
768- Only the `onScroll` event is supported on Web.
769
770### Platform Compatibility
771
772|Android|iOS|Web|
773|-|-|-|
774|✅|✅|✅|
775
776## useEvent
777
778The `useEvent` hook is a foundational tool in React Native Reanimated that provides an event handler for native events. It's particularly useful for creating custom hooks like `useScrollViewOffset` or `useAnimatedScrollHandler`.
779
780### Reference Usage
781
782```typescript
783import { useEvent } from 'react-native-reanimated';
784
785function useAnimatedPagerScrollHandler(handlers, dependencies) {
786 const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
787
788 return useEvent(
789 (event) => {
790 'worklet';
791 const { onPageScroll } = handlers;
792
793 if (onPageScroll && event.eventName.endsWith('onPageScroll')) {
794 onPageScroll(event, context);
795 }
796 },
797 ['onPageScroll'],
798 doDependenciesDiffer
799 );
800}
801
802return <Animated.View onScroll={useAnimatedPagerScrollHandler} />;
803```
804
805#### Arguments
806
807- **`handler`**: A function that receives an event object containing the native payload. This can be utilized within custom handler hooks' worklets.
808
809 - `event`: The event object, whose payload varies based on the event type.
810
811- **`eventNames` (Optional)**: An array specifying which event names should trigger the handler.
812
813- **`rebuild` (Optional)**: A boolean indicating if the handler needs to be rebuilt.
814
815#### Returns
816
817The hook returns an event handler that is invoked when a native event occurs. This handler can be connected to multiple components, triggering for each component's specific events.
818
819### Example
820
821For simpler implementations, consider using `useScrollViewOffset`.
822
823### Remarks
824
825- Note that not all scroll events are supported on the web; only `onScroll` is consistently available across browsers.
826
827### Platform Compatibility
828
829|Android|iOS|Web|
830|-|-|-|
831|✅|✅|✅|
832
833This overview provides a concise guide to using the `useEvent` hook effectively within React Native Reanimated projects.
834
835## useHandler
836
837The `useHandler` hook is a foundational tool within the React Native Reanimated library. It provides a context object and an indicator to determine if worklets require rebuilding. This functionality facilitates the creation of custom event handler hooks, such as `useScrollViewOffset` or `useAnimatedScrollHandler`.
838
839### Reference
840
841```typescript
842import { useEvent, useHandler } from "react-native-reanimated"
843
844function useAnimatedPagerScrollHandler(
845 handlers: Record<string, (event: any, context: object) => void>,
846 dependencies?: any[]
847) {
848 const { context, doDependenciesDiffer, useWeb } = useHandler(
849 handlers,
850 dependencies
851 )
852
853 return useEvent(
854 (event: any) => {
855 "worklet"
856 const { onPageScroll } = handlers
857
858 if (onPageScroll && event.eventName.endsWith("onPageScroll")) {
859 onPageScroll(event, context)
860 }
861 },
862 ["onPageScroll"],
863 doDependenciesDiffer
864 )
865}
866```
867
868#### Arguments
869
870##### `handlers`
871
872An object containing keys that correspond to native event names. The values should be individual worklets. Each worklet is triggered when its associated event is dispatched on the connected animated component.
873
874Each event worklet receives:
875
876- `event`: An event object whose payload varies based on the event type.
877- `context`: A plain JavaScript object for storing state, persisting between events. This allows communication among multiple event handlers provided as an object of worklets.
878
879##### `dependencies` (Optional)
880
881An optional array of dependencies. This is relevant when using Reanimated without its Babel plugin in a web environment.
882
883#### Returns
884
885The hook returns:
886
887- A context reused by event handlers.
888- An indicator to determine if worklets should be rebuilt.
889- A boolean, `useWeb`, to check for the web environment if different implementations are needed.
890
891### Example
892
893For simpler implementations, consider using `useScrollViewOffset`.
894
895### Platform Compatibility
896
897|Android|iOS|Web|
898|-|-|-|
899|✅|✅|✅|
900
901This documentation provides a comprehensive overview of how to utilize the `useHandler` hook within React Native Reanimated for creating custom event handlers.
902
903## Keyframe animations
904
905Keyframes provide a schema for defining animations, offering more flexibility than standard Entering and Exiting presets. They allow you to create complex animations with ease.
906
907### Reference
908
909```typescript
910import { Keyframe } from 'react-native-reanimated';
911
912const keyframe = new Keyframe({
913 0: {
914 transform: [{ rotate: '0deg' }],
915 },
916 45: {
917 transform: [{ rotate: '100deg' }],
918 easing: Easing.exp,
919 },
920 100: {
921 transform: [{ rotate: '45deg' }],
922 },
923});
924
925function App() {
926 return <Animated.View entering={keyframe} />;
927}
928```
929
930#### Arguments
931
932##### `definitions`
933
934An object containing animation definitions. The keys should be within the range of `0-100`, representing the progress of the animation. Values consist of style properties and optionally an easing function, defaulting to `Easing.linear` if not specified.
935
936Key values include:
937
938- `0` or `from`: Represents the initial state.
939- Intermediate points (e.g., `45`): Represent intermediate states.
940- `100` or `to`: Represents the final state.
941
942The key `0` (or `from`) should define the style at the start of the animation, while `100` (or `to`) defines it at the end.
943
944### Modifiers
945
946```typescript
947keyframe
948 .duration(1000)
949 .delay(500)
950 .reduceMotion(ReduceMotion.Never)
951 .withCallback((finished) => {
952 console.log(`finished without interruptions: ${finished}`)
953 })
954```
955
956- `.duration(durationMs: number)` sets the animation length in milliseconds, defaulting to `500`.
957- `.delay(durationMs: number)` specifies a delay before starting the animation, defaulting to `0`.
958- `.reduceMotion(reduceMotion: ReduceMotion)` adjusts the animation based on the device's reduced motion setting.
959- `.withCallback(callback: (finished: boolean) => void)` triggers after the animation ends, indicating if it finished without interruptions.
960
961### Remarks
962
963- Providing keyframe `0` or `from` is mandatory as it defines the initial state of the object to be animated.
964- Ensure all style properties intended for animation have an initial value in other keyframes.
965- Easing should only be applied to subsequent keyframes, not to keyframe `0`.
966- Avoid using both `0` and `from`, or `100` and `to`, as it causes parsing conflicts.
967- When animating transform styles, maintain the order of properties consistently across all keyframes.
968
969### Platform Compatibility
970
971|Android|iOS|Web|
972|-|-|-|
973|✅|✅|✅|
974
975## Your First Animation
976
977This section introduces you to the basics of Reanimated. If you're new to this library, you'll find guidance on creating a simple animation that lays the foundation for more advanced skills.
978
979### Using an Animated Component
980
981To start animating components in React Native using Reanimated, import the `Animated` object:
982
983```typescript
984import Animated from "react-native-reanimated"
985```
986
987The `Animated` object wraps native components like `View`, `ScrollView`, or `FlatList`. Use these components as you would any other JSX component:
988
989```typescript
990import Animated from 'react-native-reanimated';
991
992export default function App() {
993 return (
994 <Animated.View
995 style={{
996 width: 100,
997 height: 100,
998 backgroundColor: 'violet',
999 }}
1000 />
1001 );
1002}
1003```
1004
1005### Defining a Shared Value
1006
1007Shared values are essential for animations, acting like React state synchronized between JavaScript and the native side. Create shared values using `useSharedValue`:
1008
1009```typescript
1010import { useSharedValue } from "react-native-reanimated"
1011```
1012
1013Define shared values within your component's body to store any JS value or data structure.
1014
1015For example, set a default value of `100` for width in an `Animated.View`:
1016
1017```typescript
1018import Animated, { useSharedValue } from 'react-native-reanimated';
1019
1020export default function App() {
1021 const width = useSharedValue(100);
1022
1023 return (
1024 <Animated.View
1025 style={{
1026 width,
1027 height: 100,
1028 backgroundColor: 'violet',
1029 }}
1030 />
1031 );
1032}
1033```
1034
1035### Using a Shared Value
1036
1037Create an animation that modifies the `width` of an element by `50px` on each button press. Modify the shared value connected to the `Animated.View`'s width property.
1038
1039Access and modify values stored in shared values using their `.value` property:
1040
1041```typescript
1042import { Button, View } from 'react-native';
1043import Animated, { useSharedValue } from 'react-native-reanimated';
1044
1045export default function App() {
1046 const width = useSharedValue(100);
1047
1048 const handlePress = () => {
1049 width.value = width.value + 50;
1050 };
1051
1052 return (
1053 <View style={{ flex: 1, alignItems: 'center' }}>
1054 <Animated.View
1055 style={{
1056 width,
1057 height: 100,
1058 backgroundColor: 'violet',
1059 }}
1060 />
1061 <Button onPress={handlePress} title="Click me" />
1062 </View>
1063 );
1064}
1065```
1066
1067Avoid directly modifying shared values without using the `.value` property, as in `sv.value = sv.value + 100`.
1068
1069### Using an Animation Function
1070
1071To animate smoothly, import and use the `withSpring` function. Wrap it around the new width value to create a spring animation:
1072
1073```typescript
1074import { Button, View } from 'react-native';
1075import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
1076
1077export default function App() {
1078 const width = useSharedValue(100);
1079
1080 const handlePress = () => {
1081 width.value = withSpring(width.value + 50);
1082 };
1083
1084 return (
1085 <View style={{ flex: 1, alignItems: 'center' }}>
1086 <Animated.View
1087 style={{
1088 width,
1089 height: 100,
1090 backgroundColor: 'violet',
1091 }}
1092 />
1093 <Button onPress={handlePress} title="Click me" />
1094 </View>
1095 );
1096}
1097```
1098
1099This creates a bouncy spring animation for the element's width.
1100
1101### Summary
1102
1103In this section, you learned about:
1104
1105- `Animated` components to define animatable elements.
1106- Shared values as the driving factor of animations using `useSharedValue`.
1107- Accessing and modifying shared values via their `.value` property (e.g., `sv.value = 100;`).
1108- Creating smooth animations by modifying shared values with functions like `withSpring`.
1109
1110### What's Next?
1111
1112In the next section, you'll explore animating styles and props using `useAnimatedStyle` and `useAnimatedProps` hooks.
1113
1114## Layout transitions
1115
1116Layout transitions enable smooth animations during layout changes, which may involve alterations in size and position. Both aspects can be animated for a seamless experience.
1117
1118### Predefined Transitions
1119
1120This section outlines the available predefined layout transitions along with their animation modifiers.
1121
1122#### Linear Transition
1123
1124The linear transition animates both position and dimension uniformly.
1125
1126##### Reference
1127
1128```typescript
1129import { LinearTransition } from 'react-native-reanimated';
1130
1131function App() {
1132 return <Animated.View layout={LinearTransition} />;
1133}
1134```
1135
1136##### Modifiers
1137
1138###### Easing (Optional)
1139
1140Easing modifiers utilize the `withTiming` function to adjust animation curves over time.
1141
1142```typescript
1143LinearTransition.easing(Easing.ease)
1144```
1145
1146- `.easing(easingFunction: EasingFunction)`: Defines the animation curve. Defaults to `Easing.inOut(Easing.quad)`.
1147
1148> Note: The `.easing(...)` modifiers are ineffective when `.springify()` is used.
1149
1150###### Spring-based (Optional)
1151
1152Spring-based modifiers use the `withSpring` function, allowing for physics-based (`mass`, `damping`) or duration-based (`duration`, `dampingRatio`) configurations. These properties cannot be mixed; if both sets are provided, `duration` and `dampingRatio` take precedence.
1153
1154```typescript
1155LinearTransition.springify()
1156 .damping(30)
1157 .mass(5)
1158 .rotate(20)
1159 .stiffness(10)
1160 .overshootClamping(false)
1161 .restDisplacementThreshold(0.1)
1162 .restSpeedThreshold(5)
1163```
1164
1165- `.springify()`: Enables spring-based animation configuration.
1166- `.damping(value: number)`: Controls how quickly the spring stops moving. Defaults to `10`.
1167- `.dampingRatio(value: number)`: Determines the damping level of the spring. A value of `1` is critically damped, and values greater than `1` are overdamped. Defaults to `0.5`.
1168- `.mass(value: number)`: Represents the weight of the spring. Lower values result in faster animations. Defaults to `1`.
1169- `.rotate(degree: string)`: Allows rotation of the element.
1170- `.stiffness(value: number)`: Defines how bouncy the spring is; higher values mean less bounce. Defaults to `100`.
1171- `.overshootClamping(value: boolean)`: Determines if a spring can overshoot its target position. Defaults to `false`.
1172- `.restDisplacementThreshold(value: number)`: Sets the displacement below which the spring will settle without oscillations. Defaults to `0.001`.
1173- `.restSpeedThreshold(value: number)`: Sets the speed threshold for settling without further movement. Defaults to `2`.
1174
1175###### Common (Optional)
1176
1177```typescript
1178LinearTransition.delay(500)
1179 .reduceMotion(ReduceMotion.Never)
1180 .withInitialValues({ transform: [{ translateY: 420 }] })
1181 .withCallback((finished) => {
1182 console.log(`finished without interruptions: ${finished}`)
1183 })
1184```
1185
1186- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `300`.
1187- `.delay(duration: number)`: Specifies a delay before starting the animation (in milliseconds). Defaults to `0`.
1188- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts animation based on reduced motion settings.
1189- `.withInitialValues(values: StyleProps)`: Overrides initial animation configuration.
1190- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
1191
1192##### Remarks
1193
1194The animation concludes when both the speed is below `restSpeedThreshold` and the distance to its end is less than `restDisplacementThreshold`. If thresholds are not set, defaults apply.
1195
1196#### Sequenced Transition
1197
1198This transition animates x-position and width first, followed by y-position and height.
1199
1200##### Reference
1201
1202```typescript
1203import { SequencedTransition } from 'react-native-reanimated';
1204
1205function App() {
1206 return <Animated.View layout={SequencedTransition} />;
1207}
1208```
1209
1210##### Modifiers
1211
1212```typescript
1213SequencedTransition.duration(1000)
1214 .delay(500)
1215 .reverse()
1216 .reduceMotion(ReduceMotion.Never)
1217 .withCallback((finished) => {
1218 console.log(`finished without interruptions: ${finished}`)
1219 })
1220```
1221
1222- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `500`.
1223- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
1224- `.reverse()`: Determines if the animation should run backward. Defaults to `false`.
1225- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
1226- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
1227
1228#### Fading Transition
1229
1230The fading transition animates opacity changes while maintaining previous position and dimensions during disappearance and appearance with new ones.
1231
1232##### Reference
1233
1234```typescript
1235import { FadingTransition } from 'react-native-reanimated';
1236
1237function App() {
1238 return <Animated.View layout={FadingTransition} />;
1239}
1240```
1241
1242##### Modifiers
1243
1244```typescript
1245FadingTransition.duration(1000)
1246 .delay(500)
1247 .reduceMotion(ReduceMotion.Never)
1248 .withCallback((finished) => {
1249 console.log(`finished without interruptions: ${finished}`)
1250 })
1251```
1252
1253- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `500`.
1254- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
1255- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
1256- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
1257
1258#### Jumping Transition
1259
1260The jumping transition makes components "jump" to their new positions.
1261
1262##### Reference
1263
1264```typescript
1265import { JumpingTransition } from 'react-native-reanimated';
1266
1267function App() {
1268 return <Animated.View layout={JumpingTransition} />;
1269}
1270```
1271
1272##### Modifiers
1273
1274```typescript
1275JumpingTransition.duration(1000)
1276 .delay(500)
1277 .reduceMotion(ReduceMotion.Never)
1278 .withCallback((finished) => {
1279 console.log(`finished without interruptions: ${finished}`)
1280 })
1281```
1282
1283- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `300`.
1284- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
1285- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
1286- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
1287
1288#### Curved Transition
1289
1290The curved transition animates all parameters (`X`, `Y`, `width`, `height`) with distinct easing functions, creating a non-linear path.
1291
1292##### Reference
1293
1294```typescript
1295import { CurvedTransition } from 'react-native-reanimated';
1296
1297function App() {
1298 return <Animated.View layout={CurvedTransition} />;
1299}
1300```
1301
1302##### Modifiers
1303
1304```typescript
1305CurvedTransition.duration(1000)
1306 .delay(500)
1307 .easingX(Easing.inOut(Easing.ease))
1308 .easingY(Easing.inOut(Easing.ease))
1309 .easingWidth(Easing.inOut(Easing.ease))
1310 .easingHeight(Easing.inOut(Easing.ease))
1311 .reduceMotion(ReduceMotion.Never)
1312 .withCallback((finished) => {
1313 console.log(`finished without interruptions: ${finished}`)
1314 })
1315```
1316
1317- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `300`.
1318- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
1319- `.easingX(easing: EasingFunction)`: Defines easing for x-position.
1320- `.easingY(easing: EasingFunction)`: Defines easing for y-position.
1321- `.easingWidth(easing: EasingFunction)`: Defines easing for width.
1322- \`.easingHeight(easing: EasingFunction)): Defines easing for height.
1323- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
1324- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
1325
1326##### Remarks
1327
1328The duration is shared across all easings.
1329
1330#### Entry/Exit Transition
1331
1332This transition allows for custom animations during entry and exit by combining both into one layout. Users can define their own animations instead of using predefined ones.
1333
1334##### Reference
1335
1336```typescript
1337import { EntryExitTransition } from 'react-native-reanimated';
1338
1339function App() {
1340 return <Animated.View layout={EntryExitTransition} />;
1341}
1342```
1343
1344##### Modifiers
1345
1346```typescript
1347EntryExitTransition.duration(1000)
1348 .delay(500)
1349 .entering(CustomEnterAnimation)
1350 .exiting(CustomExitAnimation)
1351 .reduceMotion(ReduceMotion.Never)
1352 .withCallback((finished) => {
1353 console.log(`finished without interruptions: ${finished}`)
1354 })
1355```
1356
1357- `.duration(duration: number)`: Sets the animation length in milliseconds. Default depends on entry/exit animations.
1358- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
1359- `.exiting(animation)`: Defines the exit animation. Defaults to `FadeOut`.
1360- `.entering(animation)`: Defines the entry animation. Defaults to `FadeIn`.
1361- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
1362- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
1363
1364##### Remarks
1365
1366The duration is the sum of entering and exiting durations.
1367
1368#### Platform Compatibility
1369
1370|Android|iOS|Web|
1371|-|-|-|
1372|✅|✅|✅|
1373
1374This table indicates that all predefined transitions are compatible across Android, iOS, and web platforms.
1375
1376## Incremental Migration from Reanimated 1 to Reanimated 2
1377
1378The transition from Reanimated 1 to Reanimated 2 is designed to be incremental. Upon installing Reanimated 2, users can access both the old and new APIs. The latest stable version of Reanimated 1 is included in the same package, with some exceptions due to naming collisions. To maintain a cleaner API in Reanimated 2, methods from Reanimated 1 that had naming conflicts were renamed. This approach aligns with plans to gradually phase out the older API, focusing on fixing existing issues rather than developing new features for it. Consequently, this strategy introduces some breaking changes where certain method names have been altered. However, the list of renamed methods is relatively short and these methods are not frequently used.
1379
1380### Renamed Methods
1381
1382#### 1. `interpolate` to `interpolateNode`
1383
1384- **Reanimated 1**: Use `interpolate` imported directly from `react-native-reanimated`.
1385- **Reanimated 2**: Replace with `interpolateNode`. If using the class member method `AnimatedValue.interpolate`, no changes are needed.
1386
1387#### 2. `Easing` to `EasingNode`
1388
1389- **Reanimated 1**: Use `Easing` imported from `react-native-reanimated`.
1390- **Reanimated 2**: Replace with `EasingNode`.
1391
1392## Reanimated 3.x Overview
1393
1394Reanimated 3.x maintains backward compatibility with the Reanimated v2 API, ensuring that all code written for version 2.x functions seamlessly in version 3.x without requiring any modifications. However, it is important to note that Reanimated 3.x completely removes support for the Reanimated v1 API.
1395
1396For guidance on migrating from Reanimated 1.x to 2.x, please refer to the specific migration guide titled "Migration from 1.x to 2.x."
1397
1398## Customizing animations
1399
1400The previous section introduced shared values in practice using `withSpring` and `withTiming` functions for creating animations. Now, you're ready to explore customizing these animations further!
1401
1402Reanimated provides three built-in animation functions: `withTiming`, `withSpring`, and `withDecay`. This discussion will focus on the first two, with `withDecay` covered later in the Handling Gestures section.
1403
1404Customizing animation behavior in Reanimated is straightforward. You can achieve this by passing a `config` object to the second parameter of either the `withTiming` or `withSpring` function.
1405
1406### Configuring `withTiming`
1407
1408The `config` parameter for `withTiming` includes two properties: `duration` and `easing`.
1409
1410```typescript
1411import { withTiming, Easing } from "react-native-reanimated"
1412
1413withTiming(sv.value, {
1414 duration: 300,
1415 easing: Easing.inOut(Easing.quad),
1416})
1417```
1418
1419The `duration` parameter specifies the time in milliseconds for the animation to reach its target value (`toValue`). By default, this is set to `300` milliseconds.
1420
1421The `easing` parameter allows you to refine how the animation progresses over time. For instance, it can start slowly, accelerate, and then slow down again towards the end. The default easing function is `Easing.inOut(Easing.quad)`.
1422
1423To understand its impact, compare a `linear` easing with the default easing. Reanimated offers several predefined easing functions that you can experiment with in an interactive playground or refer to the full `withTiming` API documentation.
1424
1425### Configuring `withSpring`
1426
1427Unlike `withTiming`, `withSpring` is physics-based and simulates real-world spring dynamics, making animations appear more realistic.
1428
1429When adjusting springs, focus on these three properties: `mass`, `stiffness` (also known as *tension*), and `damping` (also known as *friction*).
1430
1431```typescript
1432import { withSpring } from "react-native-reanimated"
1433
1434withSpring(sv.value, {
1435 mass: 1,
1436 stiffness: 100,
1437 damping: 10,
1438})
1439```
1440
1441The `mass` of a spring affects how difficult it is to move an object and bring it to a stop. It adds inertia to the movement. A higher mass results in a more sluggish motion compared to the default.
1442
1443`Stiffness` determines the bounciness of the spring, akin to comparing a steel spring (high stiffness) with one made from soft plastic (low stiffness).
1444
1445`Damping` describes how quickly the animation concludes. Higher damping means the spring will settle faster. For example, consider a spring bouncing in air versus underwater; a vacuum would have zero friction and thus no damping.
1446
1447Reanimated includes additional properties for customizing spring animations, which you can explore in an interactive playground or through the full `withSpring` API documentation.
1448
1449### Summary
1450
1451This section covered how to customize `withTiming` and `withSpring` animation functions:
1452
1453- Both functions accept a `config` object as their second parameter.
1454- You can modify `withTiming` using `duration` and `easing`. Reanimated provides an `Easing` module for convenience.
1455- Key properties for adjusting `withSpring` include `mass`, `stiffness`, and `damping`.
1456
1457### What's Next?
1458
1459In the next section, you'll learn about animation modifiers like `withSequence` and `withRepeat`, enabling more complex and engaging animations.
1460
1461## Custom animations
1462
1463Custom animations provide full control over entering/exiting animations and layout transitions. However, they can be complex to understand and maintain. It's advisable to start with predefined presets before using custom animations.
1464
1465### Reference
1466
1467```typescript
1468function CustomAnimation(values: any) {
1469 "worklet"
1470 const animations = {
1471 // Define your animations here
1472 }
1473 const initialValues = {
1474 // Set initial values for animations
1475 }
1476 const callback = (finished: boolean) => {
1477 // Optional callback when the layout animation ends
1478 }
1479 return {
1480 initialValues,
1481 animations,
1482 callback,
1483 }
1484}
1485```
1486
1487### Custom Exiting Animation
1488
1489#### Arguments
1490
1491- `values`: Contains information about where the view was displayed and its dimensions.
1492 - `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
1493 - `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
1494 - `currentWidth`: View's width.
1495 - `currentHeight`: View's height.
1496 - `currentBorderRadius`: View's border radius.
1497 - `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
1498 - `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
1499
1500#### Example
1501
1502```typescript
1503const customExiting = (values: any) => {
1504 "worklet"
1505 const animations = {
1506 originX: withTiming(2 * WIDTH, { duration: 3000 }),
1507 opacity: withTiming(0, { duration: 2000 }),
1508 transform: [{ scale: withTiming(0.2, { duration: 3500 }) }],
1509 }
1510 const initialValues = {
1511 originX: values.currentOriginX,
1512 opacity: 1,
1513 transform: [{ scale: 1 }],
1514 }
1515 return {
1516 initialValues,
1517 animations,
1518 }
1519}
1520```
1521
1522### Custom Entering Animation
1523
1524#### Arguments
1525
1526- `values`: Contains information about where the view wants to be displayed and its dimensions.
1527 - `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
1528 - `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
1529 - `targetWidth`: View's width.
1530 - `targetHeight`: View's height.
1531 - `targetBorderRadius`: View's border radius.
1532 - `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
1533 - `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
1534
1535#### Example
1536
1537```typescript
1538const customEntering = (targetValues: any) => {
1539 "worklet"
1540 const animations = {
1541 originX: withTiming(targetValues.targetOriginX, { duration: 3000 }),
1542 opacity: withTiming(1, { duration: 2000 }),
1543 borderRadius: withDelay(1500, withTiming(40, { duration: 3000 })),
1544 transform: [
1545 { rotate: withTiming("0deg", { duration: 4000 }) },
1546 { scale: withTiming(1, { duration: 3500 }) },
1547 ],
1548 }
1549 const initialValues = {
1550 originX: -WIDTH,
1551 opacity: 0,
1552 borderRadius: 10,
1553 transform: [{ rotate: "90deg" }, { scale: 0.2 }],
1554 }
1555 return {
1556 initialValues,
1557 animations,
1558 }
1559}
1560```
1561
1562### Custom Layout Transition
1563
1564#### Arguments
1565
1566- `values`: Contains before and after information about the view's origin and dimensions.
1567 - `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
1568 - `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
1569 - `targetWidth`: View's width.
1570 - `targetHeight`: View's height.
1571 - `targetBorderRadius`: View's border radius.
1572 - `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
1573 - `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
1574 - `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system (before).
1575 - `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system (before).
1576 - `currentWidth`: View's width (before).
1577 - `currentHeight`: View's height (before).
1578 - `currentBorderRadius`: View's border radius (before).
1579 - `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system (before).
1580 - `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system (before).
1581
1582#### Example
1583
1584```typescript
1585const customLayoutTransition = (values: any) => {
1586 "worklet"
1587 return {
1588 animations: {
1589 originX: withTiming(values.targetOriginX, { duration: 1000 }),
1590 originY: withDelay(
1591 1000,
1592 withTiming(values.targetOriginY, { duration: 1000 })
1593 ),
1594 width: withSpring(values.targetWidth),
1595 height: withSpring(values.targetHeight),
1596 },
1597 initialValues: {
1598 originX: values.currentOriginX,
1599 originY: values.currentOriginY,
1600 width: values.currentWidth,
1601 height: values.currentHeight,
1602 },
1603 }
1604}
1605```
1606
1607### Remarks
1608
1609- Each Reanimated component has a shared value that keeps the current animations assigned to it. If you start a new animation for a specific property without providing an initial value, the initial value will be taken from the last animation assigned to the component. The exception is the `Entering` animation, as previous animation values are unavailable.
1610
1611### Platform Compatibility
1612
1613|Android|iOS|Web|
1614|-|-|-|
1615|✅|✅|❌|
1616
1617## Testing with Jest
1618
1619Reanimated provides a testing API based on Jest to facilitate the mocking of web-based animations. This guide outlines how to set up and use these tools effectively.
1620
1621### Reference Example
1622
1623```typescript
1624test('reference', () => {
1625 // Define some styles here
1626
1627 const { getByTestId } = render(<AnimatedComponent />);
1628 const view = getByTestId('view');
1629 const button = getByTestId('button');
1630
1631 expect(view).toHaveAnimatedStyle(style);
1632
1633 fireEvent.press(button);
1634 jest.advanceTimersByTime(250); // Advance time by half the animation duration (500ms)
1635
1636 style.width = 50; // Update width to reflect state after 250ms
1637 expect(view).toHaveAnimatedStyle(style);
1638});
1639```
1640
1641### Setup Instructions
1642
1643To set up Jest for testing with Reanimated, add the following line to your `jest-setup.js` file:
1644
1645```typescript
1646require("react-native-reanimated").setUpTests()
1647```
1648
1649- The `setUpTests()` function can accept an optional configuration object. By default, it uses `{ fps: 60 }`.
1650
1651Ensure that your `jest.config.js` includes:
1652
1653```typescript
1654preset: 'react-native',
1655setupFilesAfterEnv: ['./jest-setup.js'],
1656```
1657
1658**Caution:** For Jest versions older than 28, use the `setupFiles` property instead of `setupFilesAfterEnv`.
1659
1660### API Overview
1661
1662#### Style Checker
1663
1664- **`expect(component).toHaveAnimatedStyle(expectedStyle)`**: Verifies that selected styles match the current component styles.
1665
1666 - `component`: The component being tested.
1667 - `expectedStyle`: Expected styles, e.g., `{ width: 100 }`.
1668
1669- **`expect(component).toHaveAnimatedStyle(expectedStyle, {exact: true})`**: Ensures all current component styles match expected styles.
1670
1671- **`expect(component).toHaveAnimatedProps(expectedProps)`** (Available from version 3.17.2): Verifies that selected props match the current component props.
1672
1673 - `component`: The component being tested.
1674 - `expectedProps`: Expected props, e.g., `{ text: 'name' }`.
1675
1676- **`getDefaultStyle(component)`**: Retrieves all styles of the tested component.
1677
1678#### Timers
1679
1680Use Jest's fake timers to control animation progress. Refer to the Jest documentation for a comprehensive guide on mocking timers.
1681
1682```typescript
1683jest.useFakeTimers()
1684// Trigger animation
1685jest.runAllTimers()
1686
1687// For more precise control:
1688jest.advanceTimersByTime(250)
1689```
1690
1691### Example Test Case
1692
1693Here is an example demonstrating how to test animations:
1694
1695```typescript
1696test('withTiming animation', () => {
1697 const style = getDefaultStyle();
1698
1699 const { getByTestId } = render(<AnimatedComponent />);
1700 const view = getByTestId('view');
1701 const button = getByTestId('button');
1702
1703 expect(view.props.style.width).toBe(0);
1704 expect(view).toHaveAnimatedStyle(style);
1705
1706 fireEvent.press(button);
1707 jest.advanceTimersByTime(600); // Advance time by the full animation duration
1708
1709 style.width = 100;
1710 expect(view).toHaveAnimatedStyle(style);
1711});
1712```
1713
1714Additional examples can be found in the `react-native-reanimated` repository, such as `SharedValue.test.tsx` and `Animation.test.tsx`.
1715
1716### Remarks
1717
1718- Ensure tests run with Node 16 or newer.
1719- Testing `react-native-svg` props is not supported.
1720- If using a custom Babel configuration for testing, ensure Reanimated's Babel plugin is enabled.
1721
1722### Recommended Testing Libraries
1723
1724- [@testing-library/react-native](https://testing-library.com/docs/native-testing-library/intro)
1725- [@testing-library/react-hooks](https://testing-library.com/docs/react-hooks-testing-library/intro) - Useful for dealing with hooks.
1726
1727## withTiming
1728
1729`withTiming` enables you to create animations based on duration and easing functions.
1730
1731### Reference
1732
1733```typescript
1734import { withTiming } from "react-native-reanimated"
1735
1736function App() {
1737 sv.value = withTiming(0)
1738 // ...
1739}
1740```
1741
1742#### Arguments
1743
1744##### `toValue`
1745
1746The target value for the animation. Supported categories include:
1747
1748- **Numbers**: Can be a number or a string representation of a number.
1749- **Suffixed Numbers**: Strings that combine numbers and units (e.g., `"5.5%"`, `"90deg"`, `"3bananas"`). Ensure no space between the number and suffix, with the suffix containing only basic English letters.
1750- **Colors**:
1751 - Hexadecimal integer: e.g., `0xff1234`
1752 - RGB: e.g., `"rgb(100, 50, 0)"`
1753 - RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
1754 - RGB Hexadecimal: e.g., `"#53575E"`
1755 - HSL: e.g., `"hsl(0, 50%, 50%)"`
1756 - Named colors: e.g., `"dodgerblue"`
1757- **Objects**: Objects with properties that will be animated individually.
1758- **Arrays**: Arrays of numbers where each value is animated separately.
1759- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
1760
1761Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
1762
1763##### `config` (Optional)
1764
1765The configuration for timing animations. Available properties:
1766
1767|Name|Type|Default|Description|
1768|-|-|-|-|
1769|duration|`number`|300|Length of the animation in milliseconds.|
1770|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
1771|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
1772
1773###### `Easing`
1774
1775The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
1776
1777Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
1778
1779Use built-in easings by passing them to the `withTiming` config:
1780
1781```typescript
1782import { Easing } from "react-native-reanimated"
1783
1784withTiming(sv.value, {
1785 easing: Easing.bounce,
1786})
1787```
1788
1789Available functions include:
1790
1791- `back`: Animation where the object slightly moves back before moving forward.
1792- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
1793- `bounce`: Bouncing animation.
1794- `circle`: Circular function.
1795- `cubic`: Cubic function.
1796- `ease`: Simple inertial animation.
1797- `elastic(bounciness?: number)`: Spring interaction.
1798- `exp`: Exponential function.
1799- `linear`: Linear function.
1800- `poly(n: number)`: Higher power functions like quartic, quintic.
1801- `quad`: Quadratic function.
1802- `sin`: Sinusoidal function.
1803
1804Helpers to modify easing functions:
1805
1806- `in(easing: EasingFunction)`: Runs an easing function forwards.
1807- `inOut(easing: EasingFunction)`: Symmetrical easing function.
1808- `out(easing: EasingFunction)`: Runs an easing function backwards.
1809
1810##### `callback` (Optional)
1811
1812A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
1813
1814#### Returns
1815
1816`withTiming` returns an animation object representing the current state of the animation. It can be assigned to a shared value or used in a style object from `useAnimatedStyle`.
1817
1818### Example
1819
1820### Remarks
1821
1822- The callback passed as the third argument is automatically workletized and executed on the UI thread.
1823
1824### Platform Compatibility
1825
1826|Android|iOS|Web|
1827|-|-|-|
1828|✅|✅|✅|
1829
1830## useAnimatedProps
1831
1832`useAnimatedProps` is a function that allows you to create an animated properties object, which can be animated using shared values. This object is particularly useful for animating properties of third-party components.
1833
1834For style animations, consider using `useAnimatedStyle`.
1835
1836### Reference
1837
1838```typescript
1839import { useAnimatedProps } from 'react-native-reanimated';
1840
1841function App() {
1842 const animatedProps = useAnimatedProps(() => ({
1843 opacity: sv.value ? 1 : 0,
1844 }));
1845
1846 return <Animated.View animatedProps={animatedProps} />;
1847}
1848```
1849
1850#### Arguments
1851
1852##### `updater`
1853
1854A function that returns an object containing the properties you wish to animate.
1855
1856##### `dependencies` (Optional)
1857
1858An optional array of dependencies. This is only relevant when using Reanimated without the Babel plugin on the Web.
1859
1860##### `adapters` (Optional)
1861
1862An optional function or an array of functions. Adapters are useful for handling cases where property names differ between the API surface and their native representation.
1863
1864Reanimated includes two built-in adapters:
1865
1866- `SVGAdapter` for managing the `transform` property in `react-native-svg`.
1867- `TextInputAdapter`.
1868
1869You can create custom adapters using the `createAnimatedPropAdapter` function.
1870
1871Example of adapting `fill` and `stroke` properties from `react-native-svg` to animate them with Reanimated:
1872
1873```typescript
1874const adapter = createAnimatedPropAdapter(
1875 (props) => {
1876 if ("fill" in props) {
1877 props.fill = { type: 0, payload: processColor(props.fill) }
1878 }
1879 if ("stroke" in props) {
1880 props.stroke = { type: 0, payload: processColor(props.stroke) }
1881 }
1882 },
1883 ["fill", "stroke"]
1884)
1885```
1886
1887#### Color-related Properties
1888
1889Color properties from custom components often require special handling as they may not be directly interpretable by the native side. Reanimated includes built-in color processing for commonly used color properties, managed in a predefined list within `Colors.ts`.
1890
1891For color properties not included in this list, manual processing is necessary using the `processColor` function to ensure correct interpretation on the native side.
1892
1893Example of manually processing custom color properties:
1894
1895```typescript
1896import { processColor } from "react-native-reanimated"
1897
1898function App() {
1899 const animatedProps = useAnimatedProps(() => {
1900 const mainColor = interpolateColor(
1901 colorProgress.value,
1902 [0, 1],
1903 ["red", "blue"]
1904 )
1905
1906 const bgColor = interpolateColor(
1907 colorProgress.value,
1908 [0, 1],
1909 ["green", "yellow"]
1910 )
1911
1912 return {
1913 // `colors` prop is not on our list - we need to process it manually
1914 colors: processColor([mainColor, bgColor]),
1915 }
1916 })
1917}
1918```
1919
1920### Returns
1921
1922`useAnimatedProps` returns an animated properties object that should be assigned to the `animatedProps` property of an Animated component you wish to animate.
1923
1924### Example
1925
1926- You can share animated props between components to avoid code duplication.
1927- It is recommended to create adapters outside of a component's body to prevent unnecessary recalculations.
1928
1929### Platform Compatibility
1930
1931|Android|iOS|Web|
1932|-|-|-|
1933|✅|✅|✅|
1934
1935## React Native Reanimated: LayoutAnimationConfig (Version 3.x)
1936
1937### Overview
1938
1939`LayoutAnimationConfig` is a component designed to control the entering and exiting animations of its child components.
1940
1941#### Reference Code
1942
1943```typescript
1944import { LayoutAnimationConfig } from 'react-native-reanimated';
1945import * as React from 'react';
1946
1947function App() {
1948 const [show, setShow] = React.useState(true);
1949
1950 return (
1951 <LayoutAnimationConfig skipEntering>
1952 <View>
1953 {show && <Animated.View entering={PinwheelIn} exiting={PinwheelOut} />}
1954 </View>
1955 </LayoutAnimationConfig>
1956 );
1957}
1958```
1959
1960#### Arguments
1961
1962- **`skipEntering` (Optional)**: A boolean that determines if the entering animations of child components should be skipped when `LayoutAnimationConfig` is mounted.
1963
1964- **`skipExiting` (Optional)**: A boolean that determines if the exiting animations of child components should be skipped when `LayoutAnimationConfig` is unmounted.
1965
1966### Example Usage
1967
1968```typescript
1969<LayoutAnimationConfig skipEntering>
1970 {outer && (
1971 <Animated.View
1972 entering={PinwheelIn}
1973 exiting={PinwheelOut}
1974 style={styles.outerBox}>
1975 <LayoutAnimationConfig skipEntering skipExiting>
1976 {inner && (
1977 <Animated.View
1978 style={styles.box}
1979 entering={PinwheelIn}
1980 exiting={PinwheelOut}
1981 />
1982 )}
1983 </LayoutAnimationConfig>
1984 </Animated.View>
1985 )}
1986</LayoutAnimationConfig>
1987```
1988
1989### Remarks
1990
1991- **Nesting**: The `LayoutAnimationConfig` component can be nested to disable animations for a specific subset of components.
1992
1993- **FlatList Compatibility**: For `FlatList`, use the `skipEnteringExitingAnimations` prop. This automatically wraps your `FlatList` with `<LayoutAnimationConfig skipEntering skipExiting>` to manage animations when the list is mounted or unmounted.
1994
1995### Platform Compatibility
1996
1997|Android|iOS|Web|
1998|-|-|-|
1999|✅|✅|❌|
2000
2001- **Reference**
2002 - Arguments
2003- **Example**
2004- **Remarks**
2005- **Platform Compatibility**
2006
2007## Web Support
2008
2009Reanimated can be launched in a web browser, with all functionalities implemented purely in JavaScript. This may result in lower animation efficiency compared to native implementations.
2010
2011### Step 1: Install the Package
2012
2013Install `@babel/plugin-proposal-export-namespace-from` using one of the following package managers:
2014
2015- **EXPO**
2016
2017 ```bash
2018 npx expo install @babel/plugin-proposal-export-namespace-from
2019 ```
2020
2021- **NPM**
2022
2023 ```bash
2024 npm install @babel/plugin-proposal-export-namespace-from
2025 ```
2026
2027- **YARN**
2028 ```bash
2029 yarn add @babel/plugin-proposal-export-namespace-from
2030 ```
2031
2032### Step 2: Add Plugins to Config File
2033
2034Update your `babel.config.js` by adding the following plugins:
2035
2036```javascript
2037module.exports = {
2038 presets: [
2039 // Existing presets...
2040 ],
2041 plugins: [
2042 ...,
2043 '@babel/plugin-proposal-export-namespace-from',
2044 'react-native-reanimated/plugin', // Ensure this is listed last
2045 ],
2046};
2047```
2048
2049**Caution:** Make sure `react-native-reanimated/plugin` is the last plugin in the list.
2050
2051### Step 3: Launch Your App
2052
2053To start a playground app in the browser, use:
2054
2055```bash
2056yarn web
2057```
2058
2059For example applications from the Reanimated repository, execute these commands at the root of the repository:
2060
2061```bash
2062yarn && yarn build
2063```
2064
2065Then navigate to `apps/web-example` and run:
2066
2067```bash
2068yarn start
2069```
2070
2071### Webpack Support
2072
2073To use Reanimated in a Webpack app, adjust your configuration as follows:
2074
2075Example Webpack config with Reanimated support:
2076
2077```javascript
2078const HtmlWebpackPlugin = require("html-webpack-plugin")
2079const webpack = require("webpack")
2080
2081module.exports = {
2082 entry: ["babel-polyfill", "./index.js"],
2083 plugins: [
2084 new HtmlWebpackPlugin({
2085 filename: "index.html",
2086 template: "./index.html",
2087 }),
2088 new webpack.EnvironmentPlugin({ JEST_WORKER_ID: null }),
2089 new webpack.DefinePlugin({ process: { env: {} } }),
2090 ],
2091 module: {
2092 rules: [
2093 {
2094 test: /\.(js|jsx)$/,
2095 use: {
2096 loader: "babel-loader",
2097 options: {
2098 presets: [
2099 "@babel/preset-react",
2100 { plugins: ["@babel/plugin-proposal-class-properties"] },
2101 ],
2102 },
2103 },
2104 },
2105 ],
2106 },
2107 resolve: {
2108 alias: { "react-native$": "react-native-web" },
2109 extensions: [".web.js", ".js"],
2110 },
2111}
2112```
2113
2114### Web Without the Babel Plugin
2115
2116Reanimated can be used without its Babel plugin by manually passing dependency arrays to hooks. This approach is valid for both web and native platforms.
2117
2118Ensure these hooks include a dependency array as their last argument:
2119
2120- `useDerivedValue`
2121- `useAnimatedStyle`
2122- `useAnimatedProps`
2123- `useAnimatedReaction`
2124
2125Example usage:
2126
2127```javascript
2128const sv = useSharedValue(0)
2129const dv = useDerivedValue(
2130 () => sv.value + 1,
2131 [sv] // dependency array here
2132)
2133```
2134
2135**Caution:** Pass the root dependency (`sv`) rather than `sv.value`.
2136
2137Babel users must still install the `@babel/plugin-proposal-class-properties` plugin.
2138
2139#### ESLint Support
2140
2141To add ESLint support for Reanimated hooks, update your ESLint configuration:
2142
2143```json
2144{
2145 "rules": {
2146 "react-hooks/exhaustive-deps": [
2147 "error",
2148 {
2149 "additionalHooks": "(useAnimatedStyle|useDerivedValue|useAnimatedProps)"
2150 }
2151 ]
2152 }
2153}
2154```
2155
2156**Info:** This assumes the `react-hooks` ESLint plugin is installed.
2157
2158If using ESLint autofix, manually correct any `.value` additions to dependency arrays:
2159
2160```javascript
2161const sv = useSharedValue(0)
2162
2163// 🚨 bad: sv.value in array
2164const dv = useDerivedValue(() => sv.value, [sv.value])
2165
2166// ✅ good: sv in array
2167const dv = useDerivedValue(() => sv.value, [sv])
2168```
2169
2170### Solito / Next.js Compatibility
2171
2172An experimental SWC plugin is being developed. Until then, follow the "Web without a Babel Plugin" instructions.
2173
2174#### Next.js Polyfill
2175
2176To use Reanimated with Next.js/Solito, add the `raf` polyfill for `requestAnimationFrame`:
2177
2178```bash
2179yarn add raf
2180```
2181
2182Include this at the top of your `_app.tsx`:
2183
2184```javascript
2185import "raf/polyfill"
2186```
2187
2188## React Native Reanimated: List Layout Animations (Version 3.x)
2189
2190### Overview
2191
2192The `itemLayoutAnimation` feature in React Native Reanimated allows you to define layout transitions for list items when their layout changes. You can choose from predefined transitions like `LinearTransition`, or create custom ones.
2193
2194#### Example Usage
2195
2196```typescript
2197import Animated, { LinearTransition } from 'react-native-reanimated';
2198
2199function App() {
2200 return (
2201 <Animated.FlatList
2202 data={data}
2203 renderItem={renderItem}
2204 itemLayoutAnimation={LinearTransition}
2205 />
2206 );
2207}
2208```
2209
2210### Important Notes
2211
2212- **Single Column Limitation**: `itemLayoutAnimation` is only applicable to a single-column `Animated.FlatList`. The `numColumns` property must not exceed 1.
2213
2214- **Dynamic Transition Changes**: You can dynamically change or disable the `itemLayoutAnimation` by setting it to `undefined`.
2215
2216```typescript
2217import { useState } from 'react';
2218import Animated, { LinearTransition, JumpingTransition } from 'react-native-reanimated';
2219
2220function App() {
2221 const [transition, setTransition] = useState(LinearTransition);
2222
2223 const changeTransition = () => {
2224 setTransition(
2225 transition === LinearTransition ? JumpingTransition : LinearTransition
2226 );
2227 };
2228
2229 const toggleTransition = () => {
2230 setTransition(transition ? undefined : LinearTransition);
2231 };
2232
2233 return (
2234 <Animated.FlatList
2235 data={data}
2236 renderItem={renderItem}
2237 itemLayoutAnimation={transition}
2238 />
2239 );
2240}
2241```
2242
2243- **Custom Key Extractor**: If list items lack a `key` or `id` property, which are typically used by the FlatList's keyExtractor to generate unique keys for each item, you must provide your own implementation of the `keyExtractor`.
2244
2245```typescript
2246function App() {
2247 return (
2248 <Animated.FlatList
2249 data={data}
2250 renderItem={renderItem}
2251 itemLayoutAnimation={LinearTransition}
2252 keyExtractor={customKeyExtractor}
2253 />
2254 );
2255}
2256```
2257
2258### Platform Compatibility
2259
2260|Android|iOS|Web|
2261|-|-|-|
2262|✅|✅|✅|
2263
2264- **Example**
2265- **Remarks**
2266- **Platform compatibility**
2267
2268## Getting started
2269
2270The *Fundamentals* section aims to establish a solid understanding of the core concepts of Reanimated, empowering you to explore more complex scenarios independently. This section includes interactive examples, code snippets, and detailed explanations.
2271
2272### What is React Native Reanimated?
2273
2274React Native Reanimated is an advanced animation library developed by Software Mansion. It enables developers to create smooth animations and interactions that run on the UI thread with ease.
2275
2276### Quick Start
2277
2278To begin a new project using Expo:
2279
2280- **NPM**:
2281
2282 ```bash
2283 npx create-expo-app@latest my-app -e with-reanimated
2284 ```
2285
2286- **YARN**:
2287 ```bash
2288 yarn create expo-app my-app -e with-reanimated
2289 ```
2290
2291Alternatively, explore examples available on GitHub.
2292
2293### Installation
2294
2295Adding Reanimated to your project involves three main steps:
2296
2297#### Step 1: Install the Package
2298
2299Install the `react-native-reanimated` package from npm:
2300
2301- **EXPO**:
2302
2303 ```bash
2304 npx expo install react-native-reanimated
2305 ```
2306
2307- **NPM**:
2308
2309 ```bash
2310 npm install react-native-reanimated
2311 ```
2312
2313- **YARN**:
2314 ```bash
2315 yarn add react-native-reanimated
2316 ```
2317
2318#### Step 2: Add Reanimated's Babel Plugin
2319
2320Include the `react-native-reanimated/plugin` in your `babel.config.js`:
2321
2322```javascript
2323module.exports = {
2324 presets: [
2325 // existing presets
2326 ],
2327 plugins: [
2328 // other plugins,
2329 "react-native-reanimated/plugin",
2330 ],
2331}
2332```
2333
2334**Caution**: Ensure that `react-native-reanimated/plugin` is the last plugin listed.
2335
2336#### Step 3: Wrap Metro Config with Reanimated Wrapper (Recommended)
2337
2338Modify your `metro.config.js` to wrap the existing configuration using `wrapWithReanimatedMetroConfig`:
2339
2340```javascript
2341// metro.config.js
2342const {
2343 wrapWithReanimatedMetroConfig,
2344} = require("react-native-reanimated/metro-config")
2345
2346const config = {
2347 // Your existing Metro configuration options
2348}
2349
2350module.exports = wrapWithReanimatedMetroConfig(config)
2351```
2352
2353#### Step 4: Clear Metro Bundler Cache (Recommended)
2354
2355- **EXPO**:
2356
2357 ```bash
2358 npx expo start -c
2359 ```
2360
2361- **NPM**:
2362
2363 ```bash
2364 npm start -- --reset-cache
2365 ```
2366
2367- **YARN**:
2368 ```bash
2369 yarn start --reset-cache
2370 ```
2371
2372#### Expo Development Build
2373
2374For an Expo development build, update the native code in `ios` and `android` directories by running:
2375
2376```bash
2377npx expo prebuild
2378```
2379
2380#### Platform-Specific Setup
2381
2382##### Android
2383
2384No additional setup is required.
2385
2386##### iOS
2387
2388Before running your app on iOS, install pods with:
2389
2390```bash
2391cd ios && pod install && cd ..
2392```
2393
2394##### Web
2395
2396For web-targeted apps using react-native-web, it's recommended to use Expo. Install and add `@babel/plugin-proposal-export-namespace-from` Babel plugin in your `babel.config.js`:
2397
2398- **EXPO**:
2399
2400 ```bash
2401 npx expo install @babel/plugin-proposal-export-namespace-from
2402 ```
2403
2404- **NPM**:
2405
2406 ```bash
2407 npm install @babel/plugin-proposal-export-namespace-from
2408 ```
2409
2410- **YARN**:
2411 ```bash
2412 yarn add @babel/plugin-proposal-export-namespace-from
2413 ```
2414
2415Ensure your `babel.config.js` includes:
2416
2417```javascript
2418module.exports = {
2419 presets: [
2420 // existing presets
2421 ],
2422 plugins: [
2423 "@babel/plugin-proposal-export-namespace-from",
2424 "react-native-reanimated/plugin",
2425 ],
2426}
2427```
2428
2429**Note**: The `react-native-reanimated/plugin` should be listed last.
2430
2431For more advanced scenarios, such as using Reanimated with `webpack` or `Next.js`, refer to the separate Web Support guide.
2432
2433## useScrollViewOffset Hook
2434
2435The `useScrollViewOffset` hook enables the creation of animations based on a `ScrollView`'s offset. It automatically determines whether the `ScrollView` is oriented horizontally or vertically.
2436
2437### Reference
2438
2439```typescript
2440import { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
2441
2442function App() {
2443 const animatedRef = useAnimatedRef();
2444 const scrollOffset = useScrollViewOffset(animatedRef);
2445
2446 return (
2447 <Animated.ScrollView ref={animatedRef}>
2448 {/* Content goes here */}
2449 </Animated.ScrollView>
2450 );
2451}
2452```
2453
2454#### Arguments
2455
2456##### `animatedRef`
2457
2458An animated reference linked to the `ScrollView` component you wish to monitor. This animated reference must be assigned either to an Animated component or a React Native built-in component.
2459
2460##### `initialRef` (Optional)
2461
2462A shared value that can optionally be updated with the scroll offset. If not provided, a new shared value will be created internally by default.
2463
2464#### Returns
2465
2466The hook returns a shared value representing the current offset of the `ScrollView`.
2467
2468### Example Usage
2469
2470- The `animatedRef` argument can be dynamically changed, and the hook will continue to provide accurate values based on the connected `ScrollView`. For instance:
2471
2472 ```typescript
2473 useScrollViewOffset(someState ? someScrollRefA : someScrollRefB)
2474 ```
2475
2476### Platform Compatibility
2477
2478|Android|iOS|Web|
2479|-|-|-|
2480|✅|✅|✅|
2481
2482## Getting started
2483
2484The *Fundamentals* section aims to establish a solid understanding of the core concepts of Reanimated, empowering you to explore more complex scenarios independently. This section includes interactive examples, code snippets, and detailed explanations.
2485
2486### What is React Native Reanimated?
2487
2488React Native Reanimated is an advanced animation library developed by Software Mansion. It enables developers to create smooth animations and interactions that run on the UI thread with ease.
2489
2490### Quick Start
2491
2492To begin a new project using Expo:
2493
2494- **NPM**:
2495
2496 ```bash
2497 npx create-expo-app@latest my-app -e with-reanimated
2498 ```
2499
2500- **YARN**:
2501 ```bash
2502 yarn create expo-app my-app -e with-reanimated
2503 ```
2504
2505Alternatively, explore examples available on GitHub.
2506
2507### Installation
2508
2509Adding Reanimated to your project involves three main steps:
2510
2511#### Step 1: Install the Package
2512
2513Install the `react-native-reanimated` package from npm:
2514
2515- **EXPO**:
2516
2517 ```bash
2518 npx expo install react-native-reanimated
2519 ```
2520
2521- **NPM**:
2522
2523 ```bash
2524 npm install react-native-reanimated
2525 ```
2526
2527- **YARN**:
2528 ```bash
2529 yarn add react-native-reanimated
2530 ```
2531
2532#### Step 2: Add Reanimated's Babel Plugin
2533
2534Include the `react-native-reanimated/plugin` in your `babel.config.js`:
2535
2536```javascript
2537module.exports = {
2538 presets: [
2539 // existing presets
2540 ],
2541 plugins: [
2542 // other plugins,
2543 "react-native-reanimated/plugin",
2544 ],
2545}
2546```
2547
2548**Caution**: Ensure that `react-native-reanimated/plugin` is the last plugin listed.
2549
2550#### Step 3: Wrap Metro Config with Reanimated Wrapper (Recommended)
2551
2552Modify your `metro.config.js` to wrap the existing configuration using `wrapWithReanimatedMetroConfig`:
2553
2554```javascript
2555// metro.config.js
2556const {
2557 wrapWithReanimatedMetroConfig,
2558} = require("react-native-reanimated/metro-config")
2559
2560const config = {
2561 // Your existing Metro configuration options
2562}
2563
2564module.exports = wrapWithReanimatedMetroConfig(config)
2565```
2566
2567#### Step 4: Clear Metro Bundler Cache (Recommended)
2568
2569- **EXPO**:
2570
2571 ```bash
2572 npx expo start -c
2573 ```
2574
2575- **NPM**:
2576
2577 ```bash
2578 npm start -- --reset-cache
2579 ```
2580
2581- **YARN**:
2582 ```bash
2583 yarn start --reset-cache
2584 ```
2585
2586#### Expo Development Build
2587
2588For an Expo development build, update the native code in `ios` and `android` directories by running:
2589
2590```bash
2591npx expo prebuild
2592```
2593
2594#### Platform-Specific Setup
2595
2596##### Android
2597
2598No additional setup is required.
2599
2600##### iOS
2601
2602Before running your app on iOS, install pods with:
2603
2604```bash
2605cd ios && pod install && cd ..
2606```
2607
2608##### Web
2609
2610For web-targeted apps using react-native-web, it's recommended to use Expo. Install and add `@babel/plugin-proposal-export-namespace-from` Babel plugin in your `babel.config.js`:
2611
2612- **EXPO**:
2613
2614 ```bash
2615 npx expo install @babel/plugin-proposal-export-namespace-from
2616 ```
2617
2618- **NPM**:
2619
2620 ```bash
2621 npm install @babel/plugin-proposal-export-namespace-from
2622 ```
2623
2624- **YARN**:
2625 ```bash
2626 yarn add @babel/plugin-proposal-export-namespace-from
2627 ```
2628
2629Ensure your `babel.config.js` includes:
2630
2631```javascript
2632module.exports = {
2633 presets: [
2634 // existing presets
2635 ],
2636 plugins: [
2637 "@babel/plugin-proposal-export-namespace-from",
2638 "react-native-reanimated/plugin",
2639 ],
2640}
2641```
2642
2643**Note**: The `react-native-reanimated/plugin` should be listed last.
2644
2645For more advanced scenarios, such as using Reanimated with `webpack` or `Next.js`, refer to the separate Web Support guide.
2646
2647## withSpring
2648
2649`withSpring` enables the creation of spring-based animations in your application.
2650
2651### Reference
2652
2653```typescript
2654import { withSpring } from "react-native-reanimated"
2655
2656function App() {
2657 sv.value = withSpring(0)
2658 // ...
2659}
2660```
2661
2662#### Arguments
2663
2664##### `toValue`
2665
2666The target value where the animation will settle. Supported categories include:
2667
2668- **Numbers**: Can be a number or a string representation of a number.
2669
2670- **Suffixed Numbers**: Strings that combine numbers and units (e.g., `"5.5%"`, `"90deg"`) without spaces, using basic English letters for suffixes.
2671
2672- **Colors**:
2673
2674 - Hexadecimal integer: e.g., `0xff1234`
2675 - RGB: e.g., `"rgb(100, 50, 0)"`
2676 - RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
2677 - RGB Hexadecimal: e.g., `"#53575E"`
2678 - HSL: e.g., `"hsl(0, 50%, 50%)"`
2679 - Named colors: e.g., `"dodgerblue"`
2680
2681- **Objects**: Objects with properties that will be animated individually.
2682
2683- **Array**: Arrays of numbers where each value is animated separately.
2684
2685- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for separate animation.
2686
2687Note: The `toValue` must match the category of the animated shared value (e.g., animating `width` from `100px` to `50%` is not allowed).
2688
2689##### `config` (Optional)
2690
2691Configuration options for spring animations:
2692
2693**Physics-based Spring Configuration:**
2694
2695|Name|Type|Default|Description|
2696|-|-|-|-|
2697|mass (optional)|`number`|1|The weight of the spring. Lower values make the animation faster.|
2698|damping (optional)|`number`|10|Controls how quickly a spring slows down; higher values result in quicker rest.|
2699
2700**Duration-based Spring Configuration:**
2701
2702|Name|Type|Default|Description|
2703|-|-|-|-|
2704|duration (optional)|`number`|2000|Length of the animation in milliseconds. Available in Reanimated ≥ 3.2.x.|
2705|dampingRatio (optional)|`number`|0.5|Determines how damped the spring is; `1` means critically damped, and values >1 mean overdamped. Available in Reanimated ≥ 3.2.x.|
2706
2707**Note**: The `mass` and `damping` properties cannot be used simultaneously with `duration` and `dampingRatio`. When both are provided, `duration` and `dampingRatio` take precedence.
2708
2709**Common Spring Configuration:**
2710
2711|Name|Type|Default|Description|
2712|-|-|-|-|
2713|stiffness (optional)|`number`|100|Determines the bounciness of the spring.|
2714|velocity (optional)|`number`|0|Initial velocity applied to the spring equation.|
2715|overshootClamping (optional)|`boolean`|false|Prevents the spring from bouncing over the `toValue`.|
2716|restDisplacementThreshold (optional)|`number`|0.01|Displacement below which the spring will settle at `toValue`.|
2717|restSpeedThreshold (optional)|`number`|2|Speed threshold in pixels per second for settling at `toValue`.|
2718|reduceMotion (optional)|`ReduceMotion`|`ReduceMotion.System`|Determines animation response to reduced motion settings. Available in Reanimated ≥ 3.5.x.|
2719|clamp (optional)|`[number, number]`|`undefined`|Limits the movement scope; reduces bounciness if exceeded. Available in Reanimated ≥ 3.6.x.|
2720
2721##### `callback` (Optional)
2722
2723A function executed upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
2724
2725#### Returns
2726
2727`withSpring` returns an animation object representing the current state of the animation. This can be directly assigned to a shared value or used in a style object from `useAnimatedStyle`.
2728
2729### Example
2730
2731### Remarks
2732
2733- The callback provided as the third argument is automatically workletized and executed on the UI thread.
2734
2735### Platform Compatibility
2736
2737|Android|iOS|Web|
2738|-|-|-|
2739|✅|✅|✅|
2740
2741## useAnimatedRef
2742
2743The `useAnimatedRef` hook provides a way to obtain a reference to a view, which can be used in conjunction with functions like `measure`, `scrollTo`, and `useScrollViewOffset`.
2744
2745To utilize this hook, you must assign the object created by `useAnimatedRef` to the `ref` property of a component.
2746
2747### Reference
2748
2749```typescript
2750import { useAnimatedRef } from 'react-native-reanimated';
2751
2752function App() {
2753 const animatedRef = useAnimatedRef();
2754
2755 return <Animated.View ref={animatedRef} />;
2756}
2757```
2758
2759#### Arguments
2760
2761The `useAnimatedRef` hook does not accept any arguments.
2762
2763#### Returns
2764
2765This hook returns an object with a `current` property, which holds an instance of the component.
2766
2767### Example
2768
2769Here is a complete example:
2770
2771```typescript
2772export default function App() {
2773 const animatedRef = useAnimatedRef<Animated.View>();
2774
2775 return (
2776 <View style={styles.container}>
2777 <Animated.View
2778 ref={animatedRef}
2779 style={styles.box}
2780 onLayout={() => {
2781 // Access the component reference
2782 const component = animatedRef.current;
2783 }}
2784 />
2785 </View>
2786 );
2787}
2788```
2789
2790### Remarks
2791
2792- `useAnimatedRef` can be used to reference not only Animated components but any React Native component.
2793
2794- The value in the `current` property is available after the component has been mounted.
2795
2796```typescript
2797function App() {
2798 const animatedRef = useAnimatedRef();
2799
2800 console.log(animatedRef.current); // 🚩 Returns null
2801
2802 useEffect(() => {
2803 console.log(animatedRef.current); // ✅ Returns the component
2804 }, []);
2805
2806 return <View ref={animatedRef} />;
2807}
2808```
2809
2810Alternatively, you can access the value in `current` through event handlers or the `onLayout` property.
2811
2812- The value stored in the `current` property is not available on the UI thread.
2813
2814### Platform Compatibility
2815
2816|Android|iOS|Web|
2817|-|-|-|
2818|✅|✅|✅|
2819
2820## Web Support
2821
2822Reanimated can be launched in a web browser, with all functionalities implemented purely in JavaScript. This may result in lower animation efficiency compared to native implementations.
2823
2824### Step 1: Install the Package
2825
2826Install `@babel/plugin-proposal-export-namespace-from` using one of the following package managers:
2827
2828- **EXPO**
2829
2830 ```bash
2831 npx expo install @babel/plugin-proposal-export-namespace-from
2832 ```
2833
2834- **NPM**
2835
2836 ```bash
2837 npm install @babel/plugin-proposal-export-namespace-from
2838 ```
2839
2840- **YARN**
2841 ```bash
2842 yarn add @babel/plugin-proposal-export-namespace-from
2843 ```
2844
2845### Step 2: Add Plugins to Config File
2846
2847Update your `babel.config.js` by adding the following plugins:
2848
2849```javascript
2850module.exports = {
2851 presets: [
2852 // Existing presets...
2853 ],
2854 plugins: [
2855 ...,
2856 '@babel/plugin-proposal-export-namespace-from',
2857 'react-native-reanimated/plugin', // Ensure this is listed last
2858 ],
2859};
2860```
2861
2862**Caution:** Make sure `react-native-reanimated/plugin` is the last plugin in the list.
2863
2864### Step 3: Launch Your App
2865
2866To start a playground app in the browser, use:
2867
2868```bash
2869yarn web
2870```
2871
2872For example applications from the Reanimated repository, execute these commands at the root of the repository:
2873
2874```bash
2875yarn && yarn build
2876```
2877
2878Then navigate to `apps/web-example` and run:
2879
2880```bash
2881yarn start
2882```
2883
2884### Webpack Support
2885
2886To use Reanimated in a Webpack app, adjust your configuration as follows:
2887
2888Example Webpack config with Reanimated support:
2889
2890```javascript
2891const HtmlWebpackPlugin = require("html-webpack-plugin")
2892const webpack = require("webpack")
2893
2894module.exports = {
2895 entry: ["babel-polyfill", "./index.js"],
2896 plugins: [
2897 new HtmlWebpackPlugin({
2898 filename: "index.html",
2899 template: "./index.html",
2900 }),
2901 new webpack.EnvironmentPlugin({ JEST_WORKER_ID: null }),
2902 new webpack.DefinePlugin({ process: { env: {} } }),
2903 ],
2904 module: {
2905 rules: [
2906 {
2907 test: /\.(js|jsx)$/,
2908 use: {
2909 loader: "babel-loader",
2910 options: {
2911 presets: [
2912 "@babel/preset-react",
2913 { plugins: ["@babel/plugin-proposal-class-properties"] },
2914 ],
2915 },
2916 },
2917 },
2918 ],
2919 },
2920 resolve: {
2921 alias: { "react-native$": "react-native-web" },
2922 extensions: [".web.js", ".js"],
2923 },
2924}
2925```
2926
2927### Web Without the Babel Plugin
2928
2929Reanimated can be used without its Babel plugin by manually passing dependency arrays to hooks. This approach is valid for both web and native platforms.
2930
2931Ensure these hooks include a dependency array as their last argument:
2932
2933- `useDerivedValue`
2934- `useAnimatedStyle`
2935- `useAnimatedProps`
2936- `useAnimatedReaction`
2937
2938Example usage:
2939
2940```javascript
2941const sv = useSharedValue(0)
2942const dv = useDerivedValue(
2943 () => sv.value + 1,
2944 [sv] // dependency array here
2945)
2946```
2947
2948**Caution:** Pass the root dependency (`sv`) rather than `sv.value`.
2949
2950Babel users must still install the `@babel/plugin-proposal-class-properties` plugin.
2951
2952#### ESLint Support
2953
2954To add ESLint support for Reanimated hooks, update your ESLint configuration:
2955
2956```json
2957{
2958 "rules": {
2959 "react-hooks/exhaustive-deps": [
2960 "error",
2961 {
2962 "additionalHooks": "(useAnimatedStyle|useDerivedValue|useAnimatedProps)"
2963 }
2964 ]
2965 }
2966}
2967```
2968
2969**Info:** This assumes the `react-hooks` ESLint plugin is installed.
2970
2971If using ESLint autofix, manually correct any `.value` additions to dependency arrays:
2972
2973```javascript
2974const sv = useSharedValue(0)
2975
2976// 🚨 bad: sv.value in array
2977const dv = useDerivedValue(() => sv.value, [sv.value])
2978
2979// ✅ good: sv in array
2980const dv = useDerivedValue(() => sv.value, [sv])
2981```
2982
2983### Solito / Next.js Compatibility
2984
2985An experimental SWC plugin is being developed. Until then, follow the "Web without a Babel Plugin" instructions.
2986
2987#### Next.js Polyfill
2988
2989To use Reanimated with Next.js/Solito, add the `raf` polyfill for `requestAnimationFrame`:
2990
2991```bash
2992yarn add raf
2993```
2994
2995Include this at the top of your `_app.tsx`:
2996
2997```javascript
2998import "raf/polyfill"
2999```
3000
3001## runOnJS
3002
3003The `runOnJS` function allows you to asynchronously execute functions that are not workletized on the UI thread. This is particularly useful for most external libraries, as their functions typically lack the `"worklet"` directive.
3004
3005`runOnJS` is commonly used to update React state either after an animation completes or conditionally within a gesture interaction.
3006
3007### Reference
3008
3009```typescript
3010import { runOnJS } from "react-native-reanimated"
3011
3012function App() {
3013 // Executing on the UI thread
3014 runOnJS(navigation.goBack)()
3015}
3016```
3017
3018#### Arguments
3019
3020##### `fn`
3021
3022A reference to a function you wish to execute on the JavaScript thread from the UI thread. Any arguments for your function must be passed to the function returned by `runOnJS`, e.g., `runOnJS(setValue)(10);`.
3023
3024#### Returns
3025
3026`runOnJS` returns a function that accepts arguments for the original function provided as its first argument. This returned function can be safely executed on the UI thread.
3027
3028**Note:** Ensure you call the function returned from `runOnJS`.
3029
3030### Example
3031
3032### Remarks
3033
3034- Functions passed to `runOnJS` must be defined within the JavaScript thread scope, such as in a component body or global scope. The following code will not work because `myFunction` is defined inside the `withTiming` callback, which runs on the UI thread:
3035
3036 ```typescript
3037 withTiming(0, {}, () => {
3038 // myFunction is defined on the UI thread 🚨
3039 const myFunction = () => {
3040 // ...
3041 }
3042 runOnJS(myFunction)() // 💥
3043 })
3044 ```
3045
3046- A common mistake is to execute a function inside `runOnJS` like this: ~~`runOnJS(setValue(10))()`~~. The correct usage would be `runOnJS(setValue)(10)`.
3047
3048- It's safe to run functions via `runOnJS` on the JavaScript thread, as it has no adverse effects.
3049
3050### Platform Compatibility
3051
3052|Android|iOS|Web|
3053|-|-|-|
3054|✅|✅|✅|
3055
3056## withTiming
3057
3058`withTiming` enables you to create animations based on duration and easing functions.
3059
3060### Reference
3061
3062```typescript
3063import { withTiming } from "react-native-reanimated"
3064
3065function App() {
3066 sv.value = withTiming(0)
3067 // ...
3068}
3069```
3070
3071#### Arguments
3072
3073##### `toValue`
3074
3075The target value for the animation. Supported categories include:
3076
3077- **Numbers**: Can be a number or a string representation of a number.
3078- **Suffixed Numbers**: Strings that combine numbers and units (e.g., `"5.5%"`, `"90deg"`, `"3bananas"`). Ensure no space between the number and suffix, with the suffix containing only basic English letters.
3079- **Colors**:
3080 - Hexadecimal integer: e.g., `0xff1234`
3081 - RGB: e.g., `"rgb(100, 50, 0)"`
3082 - RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
3083 - RGB Hexadecimal: e.g., `"#53575E"`
3084 - HSL: e.g., `"hsl(0, 50%, 50%)"`
3085 - Named colors: e.g., `"dodgerblue"`
3086- **Objects**: Objects with properties that will be animated individually.
3087- **Arrays**: Arrays of numbers where each value is animated separately.
3088- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
3089
3090Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
3091
3092##### `config` (Optional)
3093
3094The configuration for timing animations. Available properties:
3095
3096|Name|Type|Default|Description|
3097|-|-|-|-|
3098|duration|`number`|300|Length of the animation in milliseconds.|
3099|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
3100|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
3101
3102###### `Easing`
3103
3104The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
3105
3106Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
3107
3108Use built-in easings by passing them to the `withTiming` config:
3109
3110```typescript
3111import { Easing } from "react-native-reanimated"
3112
3113withTiming(sv.value, {
3114 easing: Easing.bounce,
3115})
3116```
3117
3118Available functions include:
3119
3120- `back`: Animation where the object slightly moves back before moving forward.
3121- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
3122- `bounce`: Bouncing animation.
3123- `circle`: Circular function.
3124- `cubic`: Cubic function.
3125- `ease`: Simple inertial animation.
3126- `elastic(bounciness?: number)`: Spring interaction.
3127- `exp`: Exponential function.
3128- `linear`: Linear function.
3129- `poly(n: number)`: Higher power functions like quartic, quintic.
3130- `quad`: Quadratic function.
3131- `sin`: Sinusoidal function.
3132
3133Helpers to modify easing functions:
3134
3135- `in(easing: EasingFunction)`: Runs an easing function forwards.
3136- `inOut(easing: EasingFunction)`: Symmetrical easing function.
3137- `out(easing: EasingFunction)`: Runs an easing function backwards.
3138
3139##### `callback` (Optional)
3140
3141A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
3142
3143#### Returns
3144
3145`withTiming` returns an animation object representing the current state of the animation. It can be assigned to a shared value or used in a style object from `useAnimatedStyle`.
3146
3147### Example
3148
3149### Remarks
3150
3151- The callback passed as the third argument is automatically workletized and executed on the UI thread.
3152
3153### Platform Compatibility
3154
3155|Android|iOS|Web|
3156|-|-|-|
3157|✅|✅|✅|
3158
3159## Animating styles and props
3160
3161In this section, we explore different methods for passing animation styles to components. We will differentiate between animating styles and props using `useAnimatedStyle` and `useAnimatedProps`.
3162
3163### Animating Styles
3164
3165Previously, we learned about simple animations and shared values. While inline styling works well in basic cases, it has limitations, such as not allowing access to the value stored in a shared value for complex operations.
3166
3167```typescript
3168import Animated, { useSharedValue } from 'react-native-reanimated';
3169
3170function App() {
3171 const width = useSharedValue(100);
3172
3173 return <Animated.View style={{ width }} />;
3174}
3175```
3176
3177For example, multiplying a shared value before assigning it to the `style` prop is not possible:
3178
3179```typescript
3180<Animated.View style={{ width: width * 5 }} /> // This won't work
3181```
3182
3183Consider an example where a box moves right on button press:
3184
3185```typescript
3186import { View, Button } from 'react-native';
3187import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
3188
3189function App() {
3190 const translateX = useSharedValue(0);
3191
3192 const handlePress = () => {
3193 translateX.value = withSpring(translateX.value + 50);
3194 };
3195
3196 return (
3197 <View style={styles.container}>
3198 <Animated.View style={[styles.box, { transform: [{ translateX }] }]} />
3199 <Button onPress={handlePress} title="Click me" />
3200 </View>
3201 );
3202}
3203```
3204
3205To customize shared value changes based on user input, `useAnimatedStyle` is used for more control and flexibility:
3206
3207```typescript
3208export default function App() {
3209 const translateX = useSharedValue<number>(0);
3210
3211 const handlePress = () => {
3212 translateX.value += 50;
3213 };
3214
3215 const animatedStyles = useAnimatedStyle(() => ({
3216 transform: [{ translateX: withSpring(translateX.value * 2) }],
3217 }));
3218
3219 return (
3220 <>
3221 <Animated.View style={[styles.box, animatedStyles]} />
3222 <View style={styles.container}>
3223 <Button onPress={handlePress} title="Click me" />
3224 </View>
3225 </>
3226 );
3227}
3228```
3229
3230`useAnimatedStyle` allows access to the shared value's `.value`, enabling operations like multiplication before assigning it to `style`. It also centralizes animation logic.
3231
3232### Animating Props
3233
3234While many values are animated via the `style` property, sometimes props need animating. For example, SVG elements use props instead of styles:
3235
3236```typescript
3237<Circle cx="50" cy="50" r="10" fill="blue" />
3238```
3239
3240To animate non-Reanimated components' props, wrap them with `createAnimatedComponent`:
3241
3242```typescript
3243import Animated from "react-native-reanimated"
3244import { Circle } from "react-native-svg"
3245
3246const AnimatedCircle = Animated.createAnimatedComponent(Circle)
3247```
3248
3249Animating the radius of an SVG circle can be done by passing a shared value as a prop:
3250
3251```typescript
3252import { useSharedValue } from 'react-native-reanimated';
3253import { Svg } from 'react-native-svg';
3254
3255function App() {
3256 const r = useSharedValue(10);
3257
3258 return (
3259 <Svg>
3260 <AnimatedCircle cx="50" cy="50" r={r} fill="blue" />
3261 </Svg>
3262 );
3263}
3264```
3265
3266For encapsulating animation logic and accessing `.value`, `useAnimatedProps` is used:
3267
3268```typescript
3269const AnimatedCircle = Animated.createAnimatedComponent(Circle);
3270
3271export default function App() {
3272 const r = useSharedValue<number>(20);
3273
3274 const handlePress = () => {
3275 r.value += 10;
3276 };
3277
3278 const animatedProps = useAnimatedProps(() => ({
3279 r: withTiming(r.value),
3280 }));
3281
3282 return (
3283 <View style={styles.container}>
3284 <Svg style={styles.svg}>
3285 <AnimatedCircle
3286 cx="50%"
3287 cy="50%"
3288 fill="#b58df1"
3289 animatedProps={animatedProps}
3290 />
3291 </Svg>
3292 <Button onPress={handlePress} title="Click me" />
3293 </View>
3294 );
3295}
3296```
3297
3298In `useAnimatedProps`, return an object with animatable props, then pass it to the `animatedProps` prop of an Animated component.
3299
3300### Summary
3301
3302- Inline styles are simple but limited for complex animations.
3303- Props differ from styles as they aren't passed via the `style` object.
3304- `useAnimatedStyle` and `useAnimatedProps` provide access to shared values' `.value`, enhancing animation control.
3305- Custom animatable components can be created with `Animated.createAnimatedComponent`.
3306
3307### What's Next?
3308
3309In the next section, we'll delve into animation functions and customizing their behavior.
3310
3311## useDerivedValue
3312
3313The `useDerivedValue` function allows for the creation of new reactive shared values derived from existing ones. This ensures that any changes in the original shared values automatically update the derived value.
3314
3315### Reference
3316
3317```typescript
3318import { useDerivedValue } from "react-native-reanimated"
3319
3320function App() {
3321 const derivedValue = useDerivedValue(() => {
3322 return sv.value * 50
3323 })
3324}
3325```
3326
3327#### Arguments
3328
3329##### `updater`
3330
3331A function that returns a new value constructed using shared values, React state, or other JavaScript values. This function is invoked whenever any of the shared values or states it depends on change.
3332
3333##### `dependencies` (Optional)
3334
3335An optional array specifying dependencies. This parameter is only relevant when Reanimated is used without its Babel plugin in web environments.
3336
3337#### Returns
3338
3339The `useDerivedValue` function returns a new, readonly shared value that reflects changes based on the output of the `updater` function.
3340
3341### Example
3342
3343### Remarks
3344
3345- The callback provided to the first argument is automatically workletized and executed on the UI thread.
3346
3347- You can use `useDerivedValue` without returning a value in the `updater` function to respond to changes in a shared value. For accessing previous values stored in a shared value, consider using `useAnimatedReaction`.
3348
3349### Platform Compatibility
3350
3351|Android|iOS|Web|
3352|-|-|-|
3353|✅|✅|✅|
3354
3355## runOnUI
3356
3357The `runOnUI` function allows you to asynchronously execute workletized functions on the UI thread. It is commonly used within an `useEffect` for initiating animations upon component mount or unmount, as well as with `measure` and `scrollTo` functions that are implemented solely on the UI thread.
3358
3359### Reference
3360
3361```typescript
3362import { runOnUI } from "react-native-reanimated"
3363
3364function App() {
3365 // Example usage in an event handler or effect
3366 runOnUI((greeting: string) => {
3367 console.log(`${greeting} from the UI thread`)
3368 })("Howdy")
3369
3370 // ...
3371}
3372```
3373
3374#### Arguments
3375
3376##### fn
3377
3378A reference to a function intended for execution on the UI thread, originating from the JavaScript thread. Any arguments required by your function must be passed to the function returned by `runOnUI`, e.g., `runOnUI(myWorklet)(10)`.
3379
3380#### Returns
3381
3382`runOnUI` returns a function that accepts arguments for the initially provided function.
3383
3384**Note:** Ensure you invoke the function returned from `runOnUI`.
3385
3386### Example
3387
3388### Remarks
3389
3390- When creating animations, prioritize more general solutions such as `useDerivedValue`, `useAnimatedReaction`, or executing code within gesture callbacks. Resort to using `runOnUI` only after exploring these alternatives.
3391
3392- A common error is attempting to execute a function inside of `runOnUI` like this: ~~`runOnUI(myWorklet(10))()`~~. The correct usage should be `runOnUI(myWorklet)(10)`.
3393
3394- The callback provided as an argument is automatically workletized, making it ready for execution on the UI thread.
3395
3396- Avoid executing `runOnUI` directly on the UI thread to prevent errors.
3397
3398### Platform Compatibility
3399
3400|Android|iOS|Web|
3401|-|-|-|
3402|✅|✅|✅|
3403
3404## runOnRuntime
3405
3406The `runOnRuntime` function allows you to execute workletized functions asynchronously on a separate worklet runtime, which operates on a different thread.
3407
3408### Reference
3409
3410```typescript
3411import { createWorkletRuntime, runOnRuntime } from "react-native-reanimated"
3412
3413const workletRuntime = createWorkletRuntime("background")
3414
3415function App() {
3416 // Example usage in an event handler or effect
3417 runOnRuntime(workletRuntime, (greeting) => {
3418 console.log(`${greeting} from a separate thread`)
3419 })("Howdy")
3420
3421 // ...
3422}
3423```
3424
3425#### Arguments
3426
3427##### workletRuntime
3428
3429A reference to the worklet runtime created using `createWorkletRuntime`.
3430
3431##### fn
3432
3433A function intended for execution on the UI thread from the JavaScript thread. The arguments for this function must be passed to the function returned by `runOnUI`, e.g., `runOnUI(myWorklet)(10)`.
3434
3435#### Returns
3436
3437`runOnRuntime` returns a function that accepts arguments for the function provided as its first argument.
3438
3439**Note:** Ensure you call the function returned from `runOnRuntime`.
3440
3441### Remarks
3442
3443- A common mistake is to execute a function inside of `runOnRuntime` incorrectly, such as: ~~`runOnRuntime(myWorklet(10))()`~~. The correct usage is `runOnRuntime(myWorklet)(10)`.
3444
3445- The callback passed as an argument will not be automatically workletized. You must manually add the `'worklet';` directive to enable execution on the UI thread.
3446
3447- `runOnRuntime` can be called on any runtime, including the RN runtime, UI runtime, and other worklet runtimes.
3448
3449- The function provided to `runOnRuntime` is added to an execution queue on a separate thread and executed asynchronously on the specified worklet runtime. Functions are executed in the order they were queued.
3450
3451### Platform Compatibility
3452
3453|Android|iOS|Web|
3454|-|-|-|
3455|✅|✅|❌|
3456
3457## Applying modifiers
3458
3459Reanimated provides built-in modifiers for customizing animations: `withRepeat`, `withSequence`, and `withDelay`. This guide demonstrates how to use these modifiers by creating a shake animation.
3460
3461### Starting Point
3462
3463We'll create an animated box that shakes on button press after a delay. The setup involves using `useAnimatedStyle` and the `withTiming` function to move the box 40px to the right smoothly.
3464
3465```typescript
3466export default function App() {
3467 const offset = useSharedValue<number>(0);
3468
3469 const style = useAnimatedStyle(() => ({
3470 transform: [{ translateX: offset.value }],
3471 }));
3472
3473 const OFFSET = 40;
3474
3475 const handlePress = () => {
3476 offset.value = withTiming(OFFSET);
3477 };
3478
3479 return (
3480 <View style={styles.container}>
3481 <Animated.View style={[styles.box, style]} />
3482 <Button title="shake" onPress={handlePress} />
3483 </View>
3484 );
3485}
3486```
3487
3488### Repeating an Animation
3489
3490To create a shake effect, use the `withRepeat` modifier. This allows you to repeat an animation multiple times or indefinitely.
3491
3492```typescript
3493import { withRepeat } from "react-native-reanimated"
3494
3495function App() {
3496 sv.value = withRepeat(withTiming(50), 5)
3497}
3498```
3499
3500Pass a number for repetitions or a non-positive value for infinite repetition. Use `true` as the third argument to reverse the animation direction.
3501
3502Updated example:
3503
3504```typescript
3505export default function App() {
3506 const offset = useSharedValue<number>(0);
3507
3508 const style = useAnimatedStyle(() => ({
3509 transform: [{ translateX: offset.value }],
3510 }));
3511
3512 const OFFSET = 40;
3513
3514 const handlePress = () => {
3515 offset.value = withRepeat(withTiming(OFFSET), 5, true);
3516 };
3517
3518 return (
3519 <View style={styles.container}>
3520 <Animated.View style={[styles.box, style]} />
3521 <Button title="shake" onPress={handlePress} />
3522 </View>
3523 );
3524}
3525```
3526
3527### Running Animations in a Sequence
3528
3529To enhance the animation, use `withSequence` to chain animations. This modifier starts the next animation when the previous one ends.
3530
3531```typescript
3532import { withSequence } from "react-native-reanimated"
3533
3534function App() {
3535 sv.value = withSequence(withTiming(50), withTiming(0))
3536}
3537```
3538
3539Improved example:
3540
3541```typescript
3542const TIME = 250
3543
3544const handlePress = () => {
3545 offset.value = withSequence(
3546 // start from -OFFSET
3547 withTiming(-OFFSET, { duration: TIME / 2 }),
3548 // shake between -OFFSET and OFFSET 5 times
3549 withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
3550 // go back to 0 at the end
3551 withTiming(0, { duration: TIME / 2 })
3552 )
3553}
3554```
3555
3556### Starting the Animation with Delay
3557
3558Add suspense by delaying the animation start using `withDelay`.
3559
3560```typescript
3561import { withDelay } from "react-native-reanimated"
3562
3563function App() {
3564 sv.value = withDelay(500, withTiming(0))
3565}
3566```
3567
3568Final example:
3569
3570```typescript
3571const OFFSET = 40
3572const TIME = 250
3573const DELAY = 400
3574
3575const handlePress = () => {
3576 offset.value = withDelay(
3577 DELAY,
3578 withSequence(
3579 // start from -OFFSET
3580 withTiming(-OFFSET, { duration: TIME / 2 }),
3581 // shake between -OFFSET and OFFSET 5 times
3582 withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
3583 // go back to 0 at the end
3584 withTiming(0, { duration: TIME / 2 })
3585 )
3586 )
3587}
3588```
3589
3590### Summary
3591
3592- **Modifiers**: `withRepeat`, `withSequence`, and `withDelay`.
3593- **`withRepeat`**: Repeats an animation a specified number of times or indefinitely.
3594- **`withSequence`**: Chains animations to run sequentially.
3595- **`withDelay`**: Delays the start of an animation.
3596
3597### What's Next?
3598
3599Explore handling `Tap` and `Pan` gestures, and learn about the `withDecay` animation function.
3600
3601## withDecay
3602
3603The `withDecay` function allows you to create animations that simulate objects moving under friction. These animations begin at a specified velocity and gradually slow down according to the provided deceleration rate until they come to a stop.
3604
3605### Reference
3606
3607```typescript
3608import { withDecay } from "react-native-reanimated"
3609
3610function App() {
3611 sv.value = withDecay({ velocity: 1 })
3612 // ...
3613}
3614```
3615
3616#### Arguments
3617
3618##### `config`
3619
3620Configuration for the decay animation. The following properties are available:
3621
3622|Name|Type|Default|Description|
3623|-|-|-|-|
3624|`velocity` (optional)|`number`|0|Initial velocity of the animation.|
3625|`deceleration` (optional)|`number`|0.998|Rate at which the velocity decreases over time.|
3626|`clamp` (optional)\*|`[number, number]`|\[]|Array specifying bounds to restrict the animation's range. The animation stops when either bound is reached unless `rubberBandEffect` is set to `true`. \*Required if `rubberBandEffect` is enabled.|
3627|`velocityFactor` (optional)|`number`|1|Multiplier for velocity.|
3628|`rubberBandEffect` (optional)|`boolean`|false|Enables bouncing over the limit specified in `clamp`.|
3629|`rubberBandFactor` (optional)|`number`|0.6|Determines the strength of the rubber band effect.|
3630|`reduceMotion` (optional)|`ReduceMotion`|`ReduceMotion.System`|Controls how the animation responds to the device's reduced motion accessibility setting.|
3631
3632##### `callback` (Optional)
3633
3634A function executed upon animation completion. If the animation is canceled, the callback receives `false`; otherwise, it receives `true`.
3635
3636#### Returns
3637
3638The `withDecay` function returns an animation object representing the current state of the animation. This object can be directly assigned to a shared value or used as a style object returned from `useAnimatedStyle`.
3639
3640### Example
3641
3642*Note: An example section is mentioned but not provided in the original content.*
3643
3644### Remarks
3645
3646- The callback passed as the second argument is automatically workletized and executed on the UI thread.
3647
3648### Platform Compatibility
3649
3650|Android|iOS|Web|
3651|-|-|-|
3652|✅|✅|✅|
3653
3654## createAnimatedComponent
3655
3656The `createAnimatedComponent` function enables the creation of an Animated version of any React Native component. By wrapping a component with `createAnimatedComponent`, Reanimated can animate any prop or style associated with that component.
3657
3658Reanimated includes five built-in Animated components:
3659
3660- `Animated.FlatList`
3661- `Animated.Image`
3662- `Animated.View`
3663- `Animated.ScrollView`
3664- `Animated.Text`
3665
3666To animate other React Native components, they must be wrapped using the `createAnimatedComponent` function.
3667
3668### Reference
3669
3670```typescript
3671import Animated from "react-native-reanimated"
3672import { TextInput } from "react-native"
3673
3674const AnimatedTextInput = Animated.createAnimatedComponent(TextInput)
3675```
3676
3677#### Arguments
3678
3679##### `component`
3680
3681The component you wish to make animatable. Function components must be wrapped with `React.forwardRef()`.
3682
3683#### Returns
3684
3685`createAnimatedComponent` returns a component that Reanimated can animate.
3686
3687### Example
3688
3689### Platform Compatibility
3690
3691|Android|iOS|Web|
3692|-|-|-|
3693|✅|✅|✅|
3694
3695## createWorkletRuntime
3696
3697The `createWorkletRuntime` function allows for the creation of a new JavaScript runtime that can execute worklets on threads separate from the main JavaScript or UI thread. This functionality is intended primarily for use by third-party libraries integrating with worklets. The returned value represents this runtime and should be communicated to the C++ side via JSI (JavaScript Interface) for further operations.
3698
3699### Reference
3700
3701#### Usage in JavaScript
3702
3703```typescript
3704import { createWorkletRuntime } from "react-native-reanimated"
3705
3706function App() {
3707 const runtime = createWorkletRuntime("background")
3708}
3709```
3710
3711#### Usage in C++
3712
3713```cpp
3714auto runtime = reanimated::extractWorkletRuntime(rt, runtimeValue);
3715
3716jsi::Runtime &rt = runtime->getJSIRuntime();
3717
3718auto worklet = reanimated::extractShareableOrThrow<reanimated::ShareableWorklet>(rt, workletValue);
3719
3720runtime->runGuarded(worklet, ...args);
3721```
3722
3723#### Arguments
3724
3725- **`name`**: A string identifier for the runtime that will appear in device lists within Chrome DevTools.
3726
3727- **`initializer`** (optional): A worklet executed synchronously on the same thread immediately after the runtime's creation. This can be used to inject global variables or functions into the runtime.
3728
3729#### Returns
3730
3731The `createWorkletRuntime` function returns a `WorkletRuntime`, which is represented as a `jsi::HostObject<reanimated::WorkletRuntime>`.
3732
3733### Remarks
3734
3735- Worklet runtimes include built-in support for `performance.now` and `console.*` methods. Other APIs are not available by default and must be injected or captured via worklet closures.
3736
3737- In development mode, unhandled errors thrown within the runtime (excluding those in the `initializer`) will be caught, logged to the console, and displayed in a LogBox.
3738
3739- Chrome DevTools can be used for debugging the runtime when using Hermes. The runtime appears in the devices list as specified by the `name` argument passed to `createWorkletRuntime`.
3740
3741- Shared values have limited support within worklet runtimes. To write to a shared value from the React Native (RN) runtime and read it on the worklet runtime, use `runOnRuntime`. Otherwise, updates will only reflect in the RN and UI runtimes.
3742
3743### Platform Compatibility
3744
3745|Android|iOS|Web|
3746|-|-|-|
3747|✅|✅|❌|
3748
3749## interpolate
3750
3751The `interpolate` function is used to map a numeric value from one specified range to another using linear interpolation.
3752
3753### Reference Usage
3754
3755```typescript
3756import { interpolate, Extrapolation } from "react-native-reanimated"
3757
3758function App() {
3759 const animatedStyle = useAnimatedStyle(() => ({
3760 opacity: interpolate(sv.value, [0, 100], [0, 1], Extrapolation.CLAMP),
3761 }))
3762}
3763```
3764
3765#### Parameters
3766
3767- **`value`**: A numeric value that will be mapped to the specified `output` range.
3768
3769- **`input`**: An array of numbers defining the input range for interpolation.
3770
3771- **`output`**: An array of numbers defining the output range for interpolation, which should have at least as many points as the input range.
3772
3773- **`extrapolate` (Optional)**: Determines behavior when `value` is outside the `input` range. Defaults to `Extrapolation.EXTEND`.
3774
3775 Available options:
3776
3777 - `Extrapolation.EXTEND`: Predicts values beyond the output range.
3778 - `Extrapolation.CLAMP`: Clamps the value to the edge of the output range.
3779 - `Extrapolation.IDENTITY`: Returns the provided value unchanged.
3780
3781 String equivalents include `"extend"`, `"clamp"`, and `"identity"`.
3782
3783 To apply extrapolation to a specific edge, use an object:
3784
3785 ```typescript
3786 const opacity = interpolate(sv.value, [0, 100], [0, 1], {
3787 extrapolateLeft: Extrapolation.CLAMP,
3788 })
3789 ```
3790
3791#### Return Value
3792
3793The `interpolate` function returns a value mapped within the specified output range.
3794
3795### Platform Compatibility
3796
3797|Android|iOS|Web|
3798|-|-|-|
3799|✅|✅|✅|
3800
3801## cancelAnimation
3802
3803The `cancelAnimation` function is used to stop an ongoing animation associated with a shared value in React Native Reanimated.
3804
3805### Reference
3806
3807```typescript
3808import { cancelAnimation } from "react-native-reanimated"
3809
3810function App() {
3811 const offset = useSharedValue(100)
3812
3813 const handleCancel = () => {
3814 cancelAnimation(offset)
3815 }
3816}
3817```
3818
3819#### Arguments
3820
3821- **`sharedValue`**: This is the shared value linked to an active animation that you wish to terminate. If no animation is currently running, `cancelAnimation` will have no effect.
3822
3823#### Returns
3824
3825The function returns `undefined`.
3826
3827### Example Usage
3828
3829To cancel an ongoing animation, simply call `cancelAnimation` with the relevant shared value as shown in the reference section above.
3830
3831### Remarks
3832
3833- You can restart a canceled animation by reassigning it to the same shared value using functions like `withSpring` or `withTiming`.
3834
3835### Platform Compatibility
3836
3837|Android|iOS|Web|
3838|-|-|-|
3839|✅|✅|✅|
3840
3841This function is compatible across Android, iOS, and web platforms.
3842
3843## Clamp Function in React Native Reanimated
3844
3845The `clamp` function is used to restrict a value within a specified range, ensuring it does not exceed the defined minimum and maximum bounds.
3846
3847### Reference
3848
3849```typescript
3850import { clamp } from "react-native-reanimated"
3851
3852function App() {
3853 const result = clamp(sv.value, 0, 100)
3854}
3855```
3856
3857#### Arguments
3858
3859- **`value`**: A numeric value that will be returned if it falls within the specified `min` and `max` range.
3860
3861- **`min`**: The lower bound. If the provided `value` is less than this number, `min` will be returned.
3862
3863- **`max`**: The upper bound. If the provided `value` exceeds this number, `max` will be returned.
3864
3865#### Returns
3866
3867The function returns a numeric value that lies between the specified `min` and `max` bounds.
3868
3869### Example Usage
3870
3871```typescript
3872import { clamp } from "react-native-reanimated"
3873
3874function App() {
3875 const constrainedValue = clamp(150, 0, 100) // Result will be 100
3876}
3877```
3878
3879### Platform Compatibility
3880
3881|Android|iOS|Web|
3882|-|-|-|
3883|✅|✅|✅|
3884
3885This function is compatible across Android, iOS, and Web platforms.
3886
3887## interpolateColor
3888
3889The `interpolateColor` function maps an input range to output colors using linear interpolation. This is particularly useful in animations where you want a smooth transition between colors.
3890
3891### Reference Example
3892
3893```typescript
3894import { interpolateColor } from 'react-native-reanimated';
3895
3896function App() {
3897 const progress = useSharedValue(0);
3898
3899 const animatedStyle = useAnimatedStyle(() => {
3900 return {
3901 backgroundColor: interpolateColor(
3902 progress.value,
3903 [0, 1],
3904 ['red', 'green']
3905 ),
3906 };
3907 });
3908
3909 // ...
3910
3911 return <Animated.View style={[{ width: 100, height: 100 }, animatedStyle]} />;
3912}
3913```
3914
3915#### Arguments
3916
3917- **`value`**: A number from the input range that is mapped to the output range.
3918
3919- **`input`**: An array of numbers specifying the input range for interpolation. The values should be in increasing order.
3920
3921- **`output`**: An array of color strings (e.g., `'red'`, `'#ff0000'`, `'rgba(255, 0, 0, 0.5)'`) that define the output colors. It must have at least as many points as the input range.
3922
3923- **`colorSpace`** *(Optional)*: Specifies the color space for interpolation, either `'HSV'` or `'RGB'`. Defaults to `'RGB'`.
3924
3925- **`options`** *(Optional)*: Additional parameters for color interpolation:
3926
3927 |Options|Type|Default|Description|
3928 |-|-|-|-|
3929 |`gamma`|`number`|2.2|Gamma parameter used in gamma correction.|
3930 |`useCorrectedHSVInterpolation`|`boolean`|true|Reduces the number of hues during interpolation by treating HSV as circular.|
3931
3932#### Options Explanation
3933
3934- **Gamma**: Colors on web/mobile are typically expressed in sRGB, a gamma-corrected color space. Operations like addition can yield incorrect results if performed directly in this non-linear space. To address this, colors are converted to linear space for interpolation and then back to sRGB. The default gamma value of 2.2 is commonly used for this conversion.
3935
3936- **Use Corrected HSV Interpolation**: This option optimizes hue transitions by selecting the shortest path on a circular spectrum (e.g., transitioning from yellow to purple via red instead of green and blue).
3937
3938#### Returns
3939
3940The function returns an interpolated color in `rgba(r, g, b, a)` format within the specified output range.
3941
3942### Remarks
3943
3944- The function operates similarly to the `interpolate` function but specifically outputs a color string in `rgba(r, g, b, a)` notation.
3945
3946### Platform Compatibility
3947
3948|Android|iOS|Web|
3949|-|-|-|
3950|✅|✅|✅|
3951
3952This function is versatile and compatible across major platforms, making it ideal for cross-platform applications.
3953
3954## withSequence
3955
3956`withSequence` is an animation modifier that allows animations to be executed in a sequential order.
3957
3958### Reference
3959
3960```typescript
3961import { withSequence } from "react-native-reanimated"
3962
3963function App() {
3964 sv.value = withSequence(withTiming(50), withTiming(0))
3965 // ...
3966}
3967```
3968
3969#### Arguments
3970
3971##### `reduceMotion` (Optional)
3972
3973A parameter that specifies how the animation should respond to the device's reduced motion accessibility setting.
3974
3975##### `...animations`
3976
3977Any number of animation objects that will be executed in sequence.
3978
3979#### Returns
3980
3981The `withSequence` function returns an animation object representing the current state of the animation. This object can either be directly assigned to a shared value or used as a value for a style object returned from `useAnimatedStyle`.
3982
3983### Example
3984
3985### Platform Compatibility
3986
3987|Android|iOS|Web|
3988|-|-|-|
3989|✅|✅|✅|
3990
3991## scrollTo
3992
3993The `scrollTo` function allows you to synchronously scroll a component to a specified X or Y offset.
3994
3995### Reference
3996
3997```typescript
3998import { scrollTo } from 'react-native-reanimated';
3999
4000function App() {
4001 const animatedRef = useAnimatedRef();
4002 const scrollY = useSharedValue(0);
4003
4004 useDerivedValue(() => {
4005 scrollTo(animatedRef, 0, scrollY.value, true);
4006 });
4007
4008 return (
4009 <Animated.ScrollView ref={animatedRef}>{/* ... */}</Animated.ScrollView>
4010 );
4011}
4012```
4013
4014#### Arguments
4015
4016- **`animatedRef`**: An animated reference linked to the ScrollView (or another scrollable) component you wish to scroll. This animated reference must be passed to either an Animated component or a React Native built-in component.
4017
4018- **`x`**: The pixel value for horizontal scrolling on the X axis.
4019
4020- **`y`**: The pixel value for vertical scrolling on the Y axis.
4021
4022- **`animated`**: A boolean indicating if the scroll should be smooth (`true`) or instant (`false`).
4023
4024#### Returns
4025
4026The `scrollTo` function returns `undefined`.
4027
4028### Remarks
4029
4030- The `scrollTo` function must be invoked from the UI thread.
4031- It supports `Animated.FlatList`.
4032- Typically works with other ScrollView-like and FlatList-like components if they use a `ScrollView` internally and are animated.
4033- Scrollable components need to implement the `getScrollableNode` method (and `getNativeScrollRef` for New Architecture) to be compatible with `scrollTo`.
4034
4035### Platform Compatibility
4036
4037|Android|iOS|Web|
4038|-|-|-|
4039|✅|✅|✅|
4040
4041## getRelativeCoords Functionality
4042
4043The `getRelativeCoords` function is used to determine the screen location relative to a specified view.
4044
4045### Reference Code
4046
4047```typescript
4048import { getRelativeCoords } from 'react-native-reanimated';
4049
4050const Comp = () => {
4051 const animatedRef = useAnimatedRef();
4052
4053 const gestureHandler = useAnimatedGestureHandler({
4054 onEnd: (event) => {
4055 const coords = getRelativeCoords(
4056 animatedRef,
4057 event.absoluteX,
4058 event.absoluteY
4059 );
4060 },
4061 });
4062
4063 return (
4064 <View ref={animatedRef}>
4065 <PanGestureHandler onGestureEvent={gestureHandler}>
4066 <Animated.View style={[styles.box]} />
4067 </PanGestureHandler>
4068 </View>
4069 );
4070};
4071```
4072
4073### Arguments
4074
4075- **`animatedRef`**: This is the result of `useAnimatedRef`, which extends a standard React ref to deliver the view tag on the UI thread. It should be passed as a prop to the view relative to which coordinates are needed.
4076
4077- **`absoluteX`**: A number representing the absolute x-coordinate.
4078
4079- **`absoluteY`**: A number representing the absolute y-coordinate.
4080
4081### Returns
4082
4083An object containing:
4084
4085- `x`: The relative x-coordinate.
4086- `y`: The relative y-coordinate.
4087
4088### Platform Compatibility
4089
4090|Android|iOS|Web|
4091|-|-|-|
4092|✅|✅|✅|
4093
4094## useAnimatedGestureHandler
4095
4096**Warning:**\
4097The `useAnimatedGestureHandler` hook allows for the creation of animations based on gesture handlers. It is essential to provide the object created by this hook to the `onGestureEvent` property of a gesture handler component.
4098
4099This hook necessitates that `react-native-gesture-handler` be installed and configured within your project.
4100
4101### Reference
4102
4103```typescript
4104import { useAnimatedGestureHandler } from 'react-native-reanimated';
4105import { PanGestureHandler } from 'react-native-gesture-handler';
4106
4107function App() {
4108 const x = useSharedValue(0);
4109
4110 const gestureHandler = useAnimatedGestureHandler({
4111 onStart: (_, ctx) => {
4112 ctx.startX = x.value;
4113 },
4114 onActive: (event, ctx) => {
4115 x.value = ctx.startX + event.translationX;
4116 },
4117 });
4118
4119 return (
4120 <PanGestureHandler onGestureEvent={gestureHandler}>
4121 <Animated.View />
4122 </PanGestureHandler>
4123 );
4124}
4125```
4126
4127#### Arguments
4128
4129##### `gestureHandlers`
4130
4131The primary argument is an object that can include one or more handlers. These handlers are set under the following keys: `onStart`, `onActive`, `onEnd`, `onFail`, `onCancel`, and `onFinish`.
4132
4133Each handler will be activated based on the current state of the associated gesture handler. For further details, refer to the Gesture Handler documentation. The handler receives:
4134
4135- `event` \[object] - an event object containing the payload specific to the type of gesture handler (e.g., `PanGestureHandler`, `RotationGestureHandler`).
4136
4137- `context` \[object] - a JavaScript object for storing state information. This context can be read and modified, persisting between events and across handlers for all selected states.
4138
4139##### `dependencies` (Optional)
4140
4141An optional array of dependencies is relevant only when using Reanimated without the Babel plugin on the Web.
4142
4143#### Returns
4144
4145The `useAnimatedGestureHandler` hook returns a handler object that can be attached to gesture handler components from the `react-native-gesture-handler` library. This object must be passed to the `onGestureEvent` property of a gesture handler component.
4146
4147### Example
4148
4149### Platform Compatibility
4150
4151|Android|iOS|Web|
4152|-|-|-|
4153|✅|✅|⚠️|
4154
4155- On the Web, it is necessary to pass the returned handler object to both `onGestureEvent` and `onHandlerStateChange` parameters.
4156
4157## useScrollViewOffset Hook
4158
4159The `useScrollViewOffset` hook enables the creation of animations based on a `ScrollView`'s offset. It automatically determines whether the `ScrollView` is oriented horizontally or vertically.
4160
4161### Reference
4162
4163```typescript
4164import { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
4165
4166function App() {
4167 const animatedRef = useAnimatedRef();
4168 const scrollOffset = useScrollViewOffset(animatedRef);
4169
4170 return (
4171 <Animated.ScrollView ref={animatedRef}>
4172 {/* Content goes here */}
4173 </Animated.ScrollView>
4174 );
4175}
4176```
4177
4178#### Arguments
4179
4180##### `animatedRef`
4181
4182An animated reference linked to the `ScrollView` component you wish to monitor. This animated reference must be assigned either to an Animated component or a React Native built-in component.
4183
4184##### `initialRef` (Optional)
4185
4186A shared value that can optionally be updated with the scroll offset. If not provided, a new shared value will be created internally by default.
4187
4188#### Returns
4189
4190The hook returns a shared value representing the current offset of the `ScrollView`.
4191
4192### Example Usage
4193
4194- The `animatedRef` argument can be dynamically changed, and the hook will continue to provide accurate values based on the connected `ScrollView`. For instance:
4195
4196 ```typescript
4197 useScrollViewOffset(someState ? someScrollRefA : someScrollRefB)
4198 ```
4199
4200### Platform Compatibility
4201
4202|Android|iOS|Web|
4203|-|-|-|
4204|✅|✅|✅|
4205
4206## measure
4207
4208The `measure` function allows you to synchronously obtain the dimensions and position of a view on the screen, executed on the UI thread.
4209
4210### Reference
4211
4212```typescript
4213import { measure } from 'react-native-reanimated';
4214
4215function App() {
4216 const animatedRef = useAnimatedRef();
4217
4218 const handlePress = () => {
4219 runOnUI(() => {
4220 const measurement = measure(animatedRef);
4221 if (measurement === null) {
4222 return;
4223 }
4224 // Additional logic can be added here
4225 })();
4226 };
4227
4228 return <Animated.View ref={animatedRef} />;
4229}
4230```
4231
4232#### Arguments
4233
4234- **`animatedRef`**: An animated reference linked to the component whose measurements are desired. This reference must be associated with either an Animated component or a React Native built-in component.
4235
4236#### Returns
4237
4238The `measure` function returns an object containing:
4239
4240|Field|Description|
4241|-|-|
4242|`x`|A number representing the X coordinate relative to the parent component.|
4243|`y`|A number representing the Y coordinate relative to the parent component.|
4244|`width`|A number representing the width of the component.|
4245|`height`|A number representing the height of the component.|
4246|`pageX`|A number representing the X coordinate relative to the screen.|
4247|`pageY`|A number representing the Y coordinate relative to the screen.|
4248
4249Alternatively, it returns `null` if the measurement could not be performed.
4250
4251### Remarks
4252
4253- **UI Thread Execution**: The `measure` function operates exclusively on the UI thread. When used within event handlers, it must be wrapped with the `runOnUI` function.
4254
4255- **Use in `useAnimatedStyle`**: Since `useAnimatedStyle` is initially evaluated on the JavaScript thread before views are attached to the native side, a condition like the following should be included:
4256
4257 ```typescript
4258 function App() {
4259 const animatedStyles = useAnimatedStyle(() => {
4260 if (_WORKLET) {
4261 // Safely use measure here
4262 const measurement = measure(animatedRef)
4263 }
4264 })
4265 }
4266 ```
4267
4268- **Consecutive Runs**: Subsequent executions of `useAnimatedStyle` occur on the UI thread.
4269
4270- **Alternative for Static Dimensions**: If only static dimensions are needed and measurements aren't used during animations, consider using the `onLayout` property instead.
4271
4272- **Null Check**: It's advisable to check if the measurement result is `null`, as it may happen when the reference hasn't yet attached to a view:
4273
4274 ```typescript
4275 const animatedRef = useAnimatedRef()
4276
4277 const handlePress = () => {
4278 runOnUI(() => {
4279 const measurement = measure(animatedRef)
4280
4281 if (measurement === null) {
4282 return
4283 }
4284 // Additional logic can be added here
4285 })()
4286 }
4287 ```
4288
4289- **Rendered Components Only**: `measure` is applicable only to rendered components. For example, measuring off-screen items in a `FlatList` will yield `null`.
4290
4291- **Debugger Compatibility**: The `measure` function isn't available with the Remote JS Debugger. It's recommended to use Chrome DevTools (`chrome://inspect`) for debugging React Native applications.
4292
4293### Platform Compatibility
4294
4295|Android|iOS|Web|
4296|-|-|-|
4297|✅|✅|✅|
4298
4299## useAnimatedReaction
4300
4301The `useAnimatedReaction` hook enables responses to changes in shared values, particularly useful when comparing previous and current values stored within a shared value.
4302
4303### Reference
4304
4305```typescript
4306import { useAnimatedReaction } from "react-native-reanimated"
4307
4308function App() {
4309 useAnimatedReaction(
4310 () => sv.value,
4311 (currentValue, previousValue) => {
4312 if (currentValue !== previousValue) {
4313 // perform an action ✨
4314 }
4315 }
4316 )
4317
4318 // ...
4319}
4320```
4321
4322#### Arguments
4323
4324##### `prepare`
4325
4326A function returning the value to which you want to react. This returned value serves as the first parameter for the `react` argument.
4327
4328```typescript
4329function App() {
4330 useAnimatedReaction(
4331 () => Math.floor(sv.value),
4332 (currentValue, previousValue) => {
4333 // ...
4334 }
4335 )
4336}
4337```
4338
4339##### `react`
4340
4341A function that responds to changes in the value provided by the `prepare` function. It receives two parameters: the current value from `prepare` and the previous value, initially set to `null`.
4342
4343```typescript
4344function App() {
4345 useAnimatedReaction(
4346 () => Math.floor(sv.value),
4347 (currentValue, previousValue) => {
4348 // ...
4349 }
4350 )
4351}
4352```
4353
4354##### `dependencies` (Optional)
4355
4356An optional array of dependencies. This is only relevant when using Reanimated without the Babel plugin on the Web.
4357
4358#### Returns
4359
4360The `useAnimatedReaction` hook returns `undefined`.
4361
4362### Example
4363
4364### Remarks
4365
4366- Avoid mutating the same shared value in the `react` function that was used in the `prepare` function to prevent infinite loops.
4367
4368```typescript
4369function App() {
4370 useAnimatedReaction(
4371 () => width.value,
4372 (currentValue) => {
4373 // 🚨 An infinite loop!
4374 width.value += currentValue
4375 }
4376 )
4377}
4378```
4379
4380- Callbacks for both `prepare` and `react` are automatically workletized, running on the UI thread.
4381
4382- While you can use `useAnimatedReaction` to react to any stateful React value, it's generally better to use a `useEffect` for such purposes.
4383
4384### Platform Compatibility
4385
4386|Android|iOS|Web|
4387|-|-|-|
4388|✅|✅|✅|
4389
4390## Animating styles and props
4391
4392In this section, we explore different methods for passing animation styles to components. We will differentiate between animating styles and props using `useAnimatedStyle` and `useAnimatedProps`.
4393
4394### Animating Styles
4395
4396Previously, we learned about simple animations and shared values. While inline styling works well in basic cases, it has limitations, such as not allowing access to the value stored in a shared value for complex operations.
4397
4398```typescript
4399import Animated, { useSharedValue } from 'react-native-reanimated';
4400
4401function App() {
4402 const width = useSharedValue(100);
4403
4404 return <Animated.View style={{ width }} />;
4405}
4406```
4407
4408For example, multiplying a shared value before assigning it to the `style` prop is not possible:
4409
4410```typescript
4411<Animated.View style={{ width: width * 5 }} /> // This won't work
4412```
4413
4414Consider an example where a box moves right on button press:
4415
4416```typescript
4417import { View, Button } from 'react-native';
4418import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
4419
4420function App() {
4421 const translateX = useSharedValue(0);
4422
4423 const handlePress = () => {
4424 translateX.value = withSpring(translateX.value + 50);
4425 };
4426
4427 return (
4428 <View style={styles.container}>
4429 <Animated.View style={[styles.box, { transform: [{ translateX }] }]} />
4430 <Button onPress={handlePress} title="Click me" />
4431 </View>
4432 );
4433}
4434```
4435
4436To customize shared value changes based on user input, `useAnimatedStyle` is used for more control and flexibility:
4437
4438```typescript
4439export default function App() {
4440 const translateX = useSharedValue<number>(0);
4441
4442 const handlePress = () => {
4443 translateX.value += 50;
4444 };
4445
4446 const animatedStyles = useAnimatedStyle(() => ({
4447 transform: [{ translateX: withSpring(translateX.value * 2) }],
4448 }));
4449
4450 return (
4451 <>
4452 <Animated.View style={[styles.box, animatedStyles]} />
4453 <View style={styles.container}>
4454 <Button onPress={handlePress} title="Click me" />
4455 </View>
4456 </>
4457 );
4458}
4459```
4460
4461`useAnimatedStyle` allows access to the shared value's `.value`, enabling operations like multiplication before assigning it to `style`. It also centralizes animation logic.
4462
4463### Animating Props
4464
4465While many values are animated via the `style` property, sometimes props need animating. For example, SVG elements use props instead of styles:
4466
4467```typescript
4468<Circle cx="50" cy="50" r="10" fill="blue" />
4469```
4470
4471To animate non-Reanimated components' props, wrap them with `createAnimatedComponent`:
4472
4473```typescript
4474import Animated from "react-native-reanimated"
4475import { Circle } from "react-native-svg"
4476
4477const AnimatedCircle = Animated.createAnimatedComponent(Circle)
4478```
4479
4480Animating the radius of an SVG circle can be done by passing a shared value as a prop:
4481
4482```typescript
4483import { useSharedValue } from 'react-native-reanimated';
4484import { Svg } from 'react-native-svg';
4485
4486function App() {
4487 const r = useSharedValue(10);
4488
4489 return (
4490 <Svg>
4491 <AnimatedCircle cx="50" cy="50" r={r} fill="blue" />
4492 </Svg>
4493 );
4494}
4495```
4496
4497For encapsulating animation logic and accessing `.value`, `useAnimatedProps` is used:
4498
4499```typescript
4500const AnimatedCircle = Animated.createAnimatedComponent(Circle);
4501
4502export default function App() {
4503 const r = useSharedValue<number>(20);
4504
4505 const handlePress = () => {
4506 r.value += 10;
4507 };
4508
4509 const animatedProps = useAnimatedProps(() => ({
4510 r: withTiming(r.value),
4511 }));
4512
4513 return (
4514 <View style={styles.container}>
4515 <Svg style={styles.svg}>
4516 <AnimatedCircle
4517 cx="50%"
4518 cy="50%"
4519 fill="#b58df1"
4520 animatedProps={animatedProps}
4521 />
4522 </Svg>
4523 <Button onPress={handlePress} title="Click me" />
4524 </View>
4525 );
4526}
4527```
4528
4529In `useAnimatedProps`, return an object with animatable props, then pass it to the `animatedProps` prop of an Animated component.
4530
4531### Summary
4532
4533- Inline styles are simple but limited for complex animations.
4534- Props differ from styles as they aren't passed via the `style` object.
4535- `useAnimatedStyle` and `useAnimatedProps` provide access to shared values' `.value`, enhancing animation control.
4536- Custom animatable components can be created with `Animated.createAnimatedComponent`.
4537
4538### What's Next?
4539
4540In the next section, we'll delve into animation functions and customizing their behavior.
4541
4542## useFrameCallback in React Native Reanimated (Version: 3.x)
4543
4544### Overview
4545
4546The `useFrameCallback` hook allows you to execute a function on every frame update within your application.
4547
4548### Reference
4549
4550```typescript
4551import { useFrameCallback } from 'react-native-reanimated';
4552
4553function App() {
4554 const frameCallback = useFrameCallback((frameInfo) => {
4555 // Increment a value with each frame update
4556 sv.value += 1;
4557 });
4558
4559 return (
4560 <Button
4561 title="Start/Stop"
4562 onPress={() => frameCallback.setActive(!frameCallback.isActive)}
4563 />
4564 );
4565}
4566```
4567
4568#### Arguments
4569
4570##### `callback`
4571
4572- A function that runs on every frame update.
4573- Receives a `frameInfo` object with the following properties:
4574 - `timestamp`: The system time (in milliseconds) when the last frame was rendered.
4575 - `timeSincePreviousFrame`: Time (in milliseconds) since the previous frame. This is `null` for the first frame after activation and approximately 16 ms on a 60 Hz display or 8 ms on a 120 Hz display, assuming no frames are dropped.
4576 - `timeSinceFirstFrame`: The time (in milliseconds) elapsed since the callback was activated.
4577
4578##### `autostart` (Optional)
4579
4580- Determines if the callback should start automatically. Defaults to `true`.
4581
4582#### Returns
4583
4584The `useFrameCallback` hook returns an object with these properties:
4585
4586- `setActive`: A function to start or stop the frame callback.
4587- `isActive`: A boolean indicating whether the callback is currently running.
4588- `callbackId`: A unique identifier for the frame callback.
4589
4590### Remarks
4591
4592- The function provided in the `callback` argument is automatically workletized and executed on the UI thread.
4593
4594### Platform Compatibility
4595
4596|Android|iOS|Web|
4597|-|-|-|
4598|✅|✅|✅|
4599
4600- Reference
4601 - Arguments
4602 - Returns
4603- Example
4604- Remarks
4605- Platform compatibility
4606
4607## Handling gestures
4608
4609This section covers handling gestures using Reanimated in conjunction with React Native Gesture Handler. We'll focus on `Tap` and `Pan` gestures and introduce the `withDecay` animation function.
4610
4611Ensure you've completed the Gesture Handler installation steps before proceeding.
4612
4613### Handling Tap Gestures
4614
4615We begin with tap gestures, which detect brief screen touches. These can be used for custom buttons or pressable elements.
4616
4617In this example, a circle grows and changes color upon touch.
4618
4619First, wrap your app in `GestureHandlerRootView` to ensure gesture functionality:
4620
4621```typescript
4622import { GestureHandlerRootView } from 'react-native-gesture-handler';
4623
4624function App() {
4625 return (
4626 <GestureHandlerRootView style={{ flex: 1 }}>
4627 {/* rest of the app */}
4628 </GestureHandlerRootView>
4629 );
4630}
4631```
4632
4633Define tap gestures using `Gesture.Tap()` and chain methods like `onBegin`, `onStart`, `onEnd`, or `onFinalize` to update shared values:
4634
4635```typescript
4636export default function App() {
4637 const pressed = useSharedValue<boolean>(false);
4638
4639 const tap = Gesture.Tap()
4640 .onBegin(() => {
4641 pressed.value = true;
4642 })
4643 .onFinalize(() => {
4644 pressed.value = false;
4645 });
4646```
4647
4648Access shared values safely as gesture callbacks are automatically workletized.
4649
4650Define animation logic using `withTiming` in `useAnimatedStyle`:
4651
4652```typescript
4653const animatedStyles = useAnimatedStyle(() => ({
4654 backgroundColor: pressed.value ? "#FFE04B" : "#B58DF1",
4655 transform: [{ scale: withTiming(pressed.value ? 1.2 : 1) }],
4656}))
4657```
4658
4659Pass the gesture to `GestureDetector` and apply `animatedStyles`:
4660
4661```typescript
4662 return (
4663 <GestureHandlerRootView style={styles.container}>
4664 <View style={styles.container}>
4665 <GestureDetector gesture={tap}>
4666 <Animated.View style={[styles.circle, animatedStyles]} />
4667 </GestureDetector>
4668 </View>
4669 </GestureHandlerRootView>
4670 );
4671}
4672```
4673
4674### Handling Pan Gestures
4675
4676Enhance the circle by making it draggable and bouncing back to its starting position upon release. Retain color highlight and scale effects.
4677
4678Switch from `Tap` to `Pan` gesture and add an `onChange` method:
4679
4680```typescript
4681const offset = useSharedValue<number>(0);
4682
4683const pan = Gesture.Pan()
4684 .onBegin(() => {
4685 pressed.value = true;
4686 })
4687 .onChange((event) => {
4688 offset.value = event.translationX;
4689 })
4690 .onFinalize(() => {
4691 offset.value = withSpring(0);
4692 pressed.value = false;
4693```
4694
4695Use `translationX` from the event data to move the circle. Reset `offset.value` in `onFinalize` using `withSpring`.
4696
4697Adjust `useAnimatedStyle` for handling offset:
4698
4699```typescript
4700const animatedStyles = useAnimatedStyle(() => ({
4701 transform: [
4702 { translateX: offset.value },
4703 { scale: withTiming(pressed.value ? 1.2 : 1) },
4704 ],
4705 backgroundColor: pressed.value ? "#FFE04B" : "#b58df1",
4706}))
4707```
4708
4709### Using `withDecay`
4710
4711`withDecay` retains gesture velocity for decelerating animations.
4712
4713Pass final velocity in `onFinalize` to `withDecay`:
4714
4715```typescript
4716const pan = Gesture.Pan()
4717 .onChange((event) => {
4718 offset.value += event.changeX;
4719 })
4720 .onFinalize((event) => {
4721 offset.value = withDecay({
4722 velocity: event.velocityX,
4723 rubberBandEffect: true,
4724 clamp: [
4725 -(width.value / 2) + SIZE / 2 + BOUNDARY_OFFSET,
4726 width.value / 2 - SIZE / 2 - BOUNDARY_OFFSET,
4727```
4728
4729Ensure the square stays within screen bounds.
4730
4731Explore `withDecay` API for more configuration options.
4732
4733### Summary
4734
4735This section covered gesture handling with Reanimated and Gesture Handler, focusing on `Tap`, `Pan`, and `withDecay`. Key points include:
4736
4737- Integration of Reanimated with React Native Gesture Handler.
4738- Creation of gestures like `Gesture.Pan()` or `Gesture.Tap()`.
4739- Accessing shared values in gesture callbacks without extra boilerplate.
4740- Using `withDecay` for decelerating animations based on gesture velocity.
4741
4742### What's Next?
4743
4744Explore further gestures such as Pinch and Fling by reviewing the React Native Gesture Handler documentation. The next section will delve into a glossary of terms.
4745
4746## withRepeat
4747
4748`withRepeat` is an animation modifier that allows you to repeat a specified animation a certain number of times or indefinitely.
4749
4750### Reference
4751
4752```typescript
4753import { withRepeat } from "react-native-reanimated"
4754
4755function App() {
4756 sv.value = withRepeat(withSpring(0), 5)
4757 // ...
4758}
4759```
4760
4761#### Arguments
4762
4763##### `animation`
4764
4765The animation object you wish to repeat.
4766
4767##### `numberOfReps` (Optional)
4768
4769Specifies how many times the animation should be repeated. The default is `2`.
4770
4771A non-positive value, such as `0` or `-1`, will cause the animation to repeat indefinitely until it is canceled or removed. For instance, if the component unmounts or `cancelAnimation` is invoked.
4772
4773##### `reverse` (Optional)
4774
4775Determines whether the animation should alternate directions with each repetition. The default setting is `false`.
4776
4777This feature only supports direct animation functions like `withSpring` and does not work with other animation modifiers such as `withSequence`.
4778
4779##### `callback` (Optional)
4780
4781A function that executes upon the completion of the animation. If the animation is canceled, the callback receives `false`; otherwise, it receives `true`.
4782
4783##### `reduceMotion` (Optional)
4784
4785Controls how the animation responds to the device's reduced motion accessibility setting.
4786
4787#### Returns
4788
4789The `withRepeat` function returns an animation object representing the current state of the animation. This can be directly assigned to a shared value or used as a style object returned from `useAnimatedStyle`.
4790
4791### Remarks
4792
4793- The callback provided in the fourth argument is automatically workletized and executed on the UI thread.
4794
4795### Platform Compatibility
4796
4797|Android|iOS|Web|
4798|-|-|-|
4799|✅|✅|✅|
4800
4801## useComposedEventHandler
4802
4803The `useComposedEventHandler` hook allows you to combine multiple event handlers, such as those created with `useAnimatedScrollHandler`, into a single handler.
4804
4805### Reference Example
4806
4807```typescript
4808import Animated, {
4809 useAnimatedScrollHandler,
4810 useComposedEventHandler,
4811} from 'react-native-reanimated';
4812
4813function ComposedEventHandlerExample() {
4814 const onScrollHandler1 = useAnimatedScrollHandler({
4815 onScroll(e) {
4816 console.log('Scroll handler 1 onScroll event');
4817 },
4818 });
4819
4820 const onScrollHandler2 = useAnimatedScrollHandler({
4821 onScroll(e) {
4822 console.log('Scroll handler 2 onScroll event');
4823 },
4824 });
4825
4826 const composedHandler = useComposedEventHandler([
4827 onScrollHandler1,
4828 onScrollHandler2,
4829 ]);
4830
4831 return (
4832 <View style={styles.container}>
4833 <Animated.ScrollView style={styles.scroll} onScroll={composedHandler}>
4834 <Content />
4835 </Animated.ScrollView>
4836 </View>
4837 );
4838}
4839```
4840
4841#### Arguments
4842
4843- **`handlers`**: An array of event handlers created using the `useEvent` hook. The `useComposedEventHandler` hook updates whenever there are changes in these handlers.
4844
4845#### Returns
4846
4847The hook returns a handler object that can be used with any `Animated component`. This handler should be assigned to the corresponding `onEvent` prop (e.g., `onScroll` for scroll-related handlers). For better code clarity, it's recommended to use multiple composed handlers if your aggregated handler manages various events.
4848
4849### Remarks
4850
4851- The returned handler combines the functionalities of all provided handlers. This allows multiple handlers to respond to a single event and manage different types of events with one object.
4852- It functions effectively when used with multiple `Animated components`, triggering event callbacks for each connected component.
4853
4854### Platform Compatibility
4855
4856|Android|iOS|Web|
4857|-|-|-|
4858|✅|✅|✅|
4859
4860## withDelay
4861
4862`withDelay` is an animation modifier that allows you to initiate an animation after a specified delay period.
4863
4864### Reference
4865
4866```typescript
4867import { withDelay } from "react-native-reanimated"
4868
4869function App() {
4870 sv.value = withDelay(500, withTiming(0))
4871 // ...
4872}
4873```
4874
4875#### Arguments
4876
4877- **`delayMs`**: Specifies the duration (in milliseconds) before the animation begins.
4878
4879- **`delayedAnimation`**: The animation that will be delayed.
4880
4881- **`reduceMotion`** *(Optional)*: Determines how the animation responds to the device's reduced motion accessibility setting.
4882
4883#### Returns
4884
4885The `withDelay` function returns an animation object representing the current state of the animation. This object can either be directly assigned to a shared value or used as a value for a style object returned from `useAnimatedStyle`.
4886
4887### Example
4888
4889*(Example content would go here)*
4890
4891### Platform Compatibility
4892
4893|Android|iOS|Web|
4894|-|-|-|
4895|✅|✅|✅|
4896
4897***
4898
4899## useAnimatedSensor
4900
4901`useAnimatedSensor` allows you to create animations based on device sensor data. It provides access to:
4902
4903- **Accelerometer**: Measures device acceleration (excluding gravity) along the x, y, and z axes.
4904- **Gyroscope**: Captures the rotation rate of the device along the x, y, and z axes.
4905- **Gravity**: Provides the current gravity vector along the x, y, and z axes.
4906- **Magnetic Field**: Measures the Earth's magnetic field strength and direction in microtesla (μT).
4907- **Rotation**: Represents the device orientation using Euler angles and a quaternion.
4908
4909For comprehensive documentation, refer to the Sensors guide on Android Developers and Device Motion in Apple Developer documentation.
4910
4911### Reference
4912
4913```typescript
4914import { useAnimatedSensor, SensorType } from "react-native-reanimated"
4915
4916function App() {
4917 const gyroscope = useAnimatedSensor(SensorType.GYROSCOPE)
4918
4919 useDerivedValue(() => {
4920 const { x, y, z } = gyroscope.sensor.value
4921 })
4922}
4923```
4924
4925#### Arguments
4926
4927##### `sensorType`
4928
4929Specifies the sensor type using a `SensorType` enum:
4930
4931- `ACCELEROMETER`: Measures device acceleration in m/s².
4932- `GYROSCOPE`: Captures rotation rate in radians per second.
4933- `GRAVITY`: Provides gravity vector in m/s².
4934- `MAGNETIC_FIELD`: Measures magnetic field strength in microtesla (μT).
4935- `ROTATION`: Represents orientation using Euler angles and a quaternion.
4936
4937##### `config` (Optional)
4938
4939|Name|Type|Default|Description|
4940|-|-|-|-|
4941|interval|`number \| "auto"`|`"auto"`|Time between sensor readings in milliseconds. `"auto"` matches the device's screen refresh rate.|
4942|adjustToInterfaceOrientation|`boolean`|`true`|Adjusts measurements to the current interface orientation.|
4943|iosReferenceFrame|`IOSReferenceFrame`|`IOSReferenceFrame.Auto`|Frame of reference for iOS sensors.|
4944
4945Available `IOSReferenceFrame` options:
4946
4947- `xArbitraryZVertical`: Z axis is vertical, X axis arbitrary in horizontal plane.
4948- `xArbitraryCorrectedZVertical`: Improved rotation accuracy with Z vertical and X arbitrary.
4949- `XMagneticNorthZVertical`: Z axis vertical, X points to magnetic north.
4950- `XTrueNorthZVertical`: Z axis vertical, X points to geographic north.
4951- `Auto`: Defaults based on device capabilities.
4952
4953#### Returns
4954
4955`useAnimatedSensor` returns an object:
4956
4957|Name|Type|Description|
4958|-|-|-|
4959|sensor|`SharedValue<Value3D \| ValueRotation>`|Shared value with sensor measurements.|
4960|unregister|`() => void`|Stops listening to sensor updates when called.|
4961|isAvailable|`boolean`|Indicates if the sensor is available for use.|
4962|config|`SensorConfig`|Contains sensor configuration details.|
4963
4964The shared value from the **rotation sensor** includes:
4965
4966- Euler angles: `roll`, `pitch`, `yaw`.
4967- Quaternion components: `qw`, `qx`, `qy`, `qz`.
4968- Interface orientation.
4969
4970Other sensors return measurements on x, y, z axes and interface orientation.
4971
4972`InterfaceOrientation` enum values:
4973
4974- `ROTATION_0`: Default rotation on Android, portrait on iOS.
4975- `ROTATION_90`: 90 degrees on Android, landscape right on iOS.
4976- `ROTATION_180`: 180 degrees on Android, upside down on iOS.
4977- `ROTATION_270`: 270 degrees on Android, landscape left on iOS.
4978
4979### Example
4980
4981```typescript
4982export default function App() {
4983 const gravity = useAnimatedSensor(SensorType.GRAVITY);
4984
4985 const animatedStyle = useAnimatedStyle(() => {
4986 return {
4987 transform: [
4988 { translateX: withSpring(gravity.sensor.value.x * 20) },
4989 { translateY: withSpring(gravity.sensor.value.y * 20) },
4990 ],
4991 };
4992 });
4993
4994 return (
4995 <View style={styles.container}>
4996 <Animated.View style={[styles.box, animatedStyle]} />
4997 </View>
4998 );
4999}
5000```
5001
5002### Remarks
5003
5004- On iOS, enable location services (`Settings > Privacy > Location Services`) to read sensor data.
5005- On Web, ensure the device supports sensors and the application is served over HTTPS.
5006- Most sensors operate at resolutions up to 100Hz.
5007- Sensor data can be accessed on both UI and JavaScript threads.
5008
5009### Platform Compatibility
5010
5011|Android|iOS|Web|
5012|-|-|-|
5013|✅|✅|✅|
5014
5015## dispatchCommand
5016
5017The `dispatchCommand` function enables the execution of commands directly on a native component from the UI thread.
5018
5019### Reference
5020
5021```typescript
5022import { dispatchCommand } from 'react-native-reanimated';
5023
5024function App() {
5025 const animatedRef = useAnimatedRef();
5026
5027 const gesture = Gesture.Tap().onStart(() => {
5028 dispatchCommand(animatedRef, 'focus');
5029 });
5030
5031 return (
5032 <>
5033 <AnimatedTextInput ref={animatedRef} style={styles.input} />
5034 <GestureDetector gesture={gesture}>
5035 <Button title="Focus" />
5036 </GestureDetector>
5037 </>
5038 );
5039}
5040```
5041
5042#### Arguments
5043
5044- **`animatedRef`**: An animated reference linked to the component you wish to update. This reference must be associated with either an Animated component or a React Native built-in component.
5045
5046- **`commandName`**: The name of the command to execute, such as `'focus'` or `'scrollToEnd'`.
5047
5048- **`args` (Optional)**: An array of arguments for the command. Defaults to an empty array if not provided.
5049
5050### Example
5051
5052```typescript
5053const goDown = Gesture.Tap().onStart(() => {
5054 dispatchCommand(tosRef, "scrollToEnd", [true])
5055 dispatchCommand(loginRef, "focus")
5056})
5057```
5058
5059### Remarks
5060
5061- Commands vary depending on the component. Refer to the relevant React Native documentation for available commands specific to each component.
5062
5063### Platform Compatibility
5064
5065|Android|iOS|Web|
5066|-|-|-|
5067|✅|✅|❌|
5068
5069## setNativeProps
5070
5071The `setNativeProps` function allows for the imperative updating of component properties in React Native. It serves as an escape hatch intended for specific edge cases.
5072
5073> **Caution:**\
5074> Prefer using `useAnimatedStyle` and `useAnimatedProps` when animating styles or properties, reserving `setNativeProps` for exceptional situations.
5075
5076### Reference
5077
5078```typescript
5079import { setNativeProps } from 'react-native-reanimated';
5080
5081function App() {
5082 const animatedRef = useAnimatedRef();
5083
5084 const tap = Gesture.Tap().onEnd(() => {
5085 setNativeProps(animatedRef, { text: '' });
5086 });
5087
5088 return <TextInput ref={animatedRef} />;
5089}
5090```
5091
5092#### Arguments
5093
5094- **`animatedRef`:**\
5095 An animated reference linked to the component you wish to update. This animated reference must be passed either to an Animated component or a React Native built-in component.
5096
5097- **`updates`:**\
5098 An object containing properties that need updating, which can include both style properties (e.g., `width`, `backgroundColor`) and regular properties (e.g., `text`).
5099
5100#### Returns
5101
5102The function returns `undefined`.
5103
5104### Remarks
5105
5106- Prioritize using `useAnimatedStyle` and `useAnimatedProps` for animating styles or properties.
5107- Ensure that `setNativeProps` is used exclusively on the UI thread.
5108- The `setNativeProps` function was designed to facilitate the imperative updating of props from gesture handlers. In other scenarios, it may require an additional `runOnUI` call, making React Native's built-in `setNativeProps` more efficient with fewer runtime transitions.
5109
5110### Platform Compatibility
5111
5112|Android|iOS|Web|
5113|-|-|-|
5114|✅|✅|✅|
5115
5116***
5117
5118## React Native Reanimated: useReducedMotion Hook (Version 3.x)
5119
5120### Overview
5121
5122The `useReducedMotion` hook in React Native Reanimated allows developers to check the system's reduced motion setting. This is particularly useful for disabling animations when users prefer less motion.
5123
5124### Reference
5125
5126```typescript
5127import { useReducedMotion } from "react-native-reanimated"
5128
5129function App() {
5130 const reduceMotion = useReducedMotion()
5131
5132 if (reduceMotion) {
5133 // Display static content ✨
5134 } else {
5135 // Run animations ✨
5136 }
5137
5138 // Additional logic...
5139}
5140```
5141
5142#### Returns
5143
5144The `useReducedMotion` hook returns a boolean value indicating whether the reduced motion setting was enabled at the start of the app.
5145
5146### Example Usage
5147
5148```typescript
5149import { useReducedMotion } from 'react-native-reanimated';
5150
5151function App() {
5152 const reduceMotion = useReducedMotion();
5153
5154 if (reduceMotion) {
5155 return <StaticContent />;
5156 } else {
5157 return <AnimatedContent />;
5158 }
5159}
5160```
5161
5162### Remarks
5163
5164- Changing the reduced motion setting does not trigger a component rerender.
5165- Unlike `AccessibilityInfo.isReduceMotionEnabled()`, `useReducedMotion` provides the value synchronously.
5166
5167### Platform Compatibility
5168
5169|Android|iOS|Web|
5170|-|-|-|
5171|✅|✅|✅|
5172
5173This hook is compatible across Android, iOS, and Web platforms.
5174
5175## makeMutable
5176
5177**Caution:** The use of `makeMutable` is generally discouraged. It's recommended to opt for the `useSharedValue` hook unless you are fully aware of its implications (refer to the Remarks section).
5178
5179Internally, `makeMutable` is utilized by the `useSharedValue` hook to generate a shared value. This function allows the creation of mutable values without relying on the hook, which can be beneficial in specific scenarios such as within the global scope or when managing an array of mutable values.
5180
5181The object produced by `makeMutable` mirrors that returned by the `useSharedValue` hook, ensuring consistent usage thereafter.
5182
5183### Reference
5184
5185```typescript
5186import { makeMutable } from "react-native-reanimated"
5187
5188const mv = makeMutable(100)
5189```
5190
5191#### Arguments
5192
5193##### `initial`
5194
5195This argument specifies the initial value to be stored in the mutable. It can encompass any JavaScript data type such as `number`, `string`, or `boolean`, and also includes complex structures like arrays and objects.
5196
5197#### Returns
5198
5199`makeMutable` yields a mutable value initialized with the provided `initial`. Access to the stored data is possible through its `value` property or via `get` and `set` methods.
5200
5201### Example
5202
5203### Remarks
5204
5205**Info:** The term *mutable value* refers to an object created by `makeMutable`, distinguishing it from a *shared value*, which is essentially a mutable value with automatic cleanup.
5206
5207- All remarks applicable to the `useSharedValue` hook are relevant to `makeMutable`.
5208- Avoid invoking `makeMutable` directly within component scope. Component re-renders will generate a new object, potentially resetting the initial value and losing previous state.
5209
5210```typescript
5211function App() {
5212 const [counter, setCounter] = useState(0)
5213 const mv = makeMutable(counter) // 🚨 creates a new mutable value on each render
5214
5215 useEffect(() => {
5216 const interval = setInterval(() => {
5217 setCounter((prev) => prev + 1) // updates the counter stored in component state
5218 }, 1000)
5219
5220 return () => {
5221 clearInterval(interval)
5222 }
5223 }, [mv])
5224
5225 useAnimatedReaction(
5226 () => mv.value,
5227 (value) => {
5228 console.log(value) // prints 0, 1, 2, ...
5229 }
5230 )
5231}
5232```
5233
5234- Utilize `cancelAnimation` to halt all ongoing animations on a mutable value if it becomes unnecessary and animations are still active. Exercise caution with infinite animations as they require manual cancellation.
5235
5236```typescript
5237function App() {
5238 const mv = useMemo(() => makeMutable(0), [])
5239
5240 useEffect(() => {
5241 mv.value = withRepeat(withSpring(100), -1, true) // creates an infinite animation
5242
5243 return () => {
5244 cancelAnimation(mv) // ✅ stops the infinite animation on component unmount
5245 }
5246 }, [])
5247}
5248```
5249
5250- `cancelAnimation` is not needed for non-animated values as they are automatically garbage collected when no references remain.
5251
5252```typescript
5253const someFlag = makeMutable(false)
5254
5255function App() {
5256 someFlag.value = true // ✅ no need to cancel the animation later on
5257}
5258```
5259
5260- When opting for `makeMutable`, adhere to React's rules and avoid common pitfalls associated with `useRef`, such as modifying references during rendering (see the **Pitfall** section in the useRef documentation).
5261
5262#### Comparison with `useSharedValue`
5263
5264|Feature|`makeMutable`|`useSharedValue`|
5265|-|-|-|
5266|Object Creation|Creates a new object on each call|Reuses the same object on each call|
5267|Initial Value Change|A new object is created if `initial` changes|The initially created object remains unchanged if `initialValue` changes|
5268|Scope Usage|Can be used outside of component scope|Limited to use within component scope|
5269|Loop Usage|Usable in loops with variable iterations|Usable in loops only if the number of hooks (`useSharedValue` calls) is constant|
5270|Animation Cancellation|Does not automatically cancel animations on unmount|Automatically cancels animations when the component unmounts|
5271
5272### Platform Compatibility
5273
5274|Android|iOS|Web|
5275|-|-|-|
5276|✅|✅|✅|
5277
5278## Accurate Call Stacks
5279
5280When debugging Reanimated code, developers might encounter misleading call stacks in errors or warnings. These stacks often highlight internal Reanimated code rather than pinpointing the misuse of the Reanimated API that caused the issue.
5281
5282To improve this situation, Reanimated offers a Metro configuration wrapper named `wrapWithReanimatedMetroConfig`. This tool adjusts your Metro config to enhance the accuracy of call stacks for warnings and errors generated by the Reanimated library.
5283
5284### Reference
5285
5286For more precise call stacks, import `wrapWithReanimatedMetroConfig` from `react-native-reanimated/metro-config` and use it to wrap your existing Metro configuration in the `metro.config.js` file.
5287
5288```typescript
5289// metro.config.js
5290import { wrapWithReanimatedMetroConfig } from "react-native-reanimated/metro-config"
5291
5292const config = {
5293 // Your existing Metro configuration options
5294}
5295
5296export default wrapWithReanimatedMetroConfig(config)
5297```
5298
5299### Example
5300
5301The example below illustrates the difference in call stacks before and after applying the Reanimated Metro config wrapper. The **Before** scenario shows Reanimated source code as the error origin, while the **After** scenario reveals the actual incorrect code that caused the error.
5302
5303|Before|After|
5304|-|-|
5305|||
5306
5307### Remarks
5308
5309- `wrapWithReanimatedMetroConfig` does not remove any stack frames; it only collapses irrelevant ones from Reanimated. To inspect these, you can expand collapsed stack frames by clicking on the **See N more frames** text at the bottom of the **Call Stack**.
5310
5311|Collapsed|Expanded|
5312|-|-|
5313|||
5314
5315- Some errors, especially those arising from asynchronous code, may still point to Reanimated internals instead of the exact problematic line in your code. This happens because stack traces can lose track of the original code that initiated the asynchronous operation. In such cases, manual debugging based on the error message is necessary to identify the potential cause of the problem.
5316
5317## withClamp
5318
5319`withClamp` is an animation modifier that restricts the movement of your animation within a specified range. It's typically used in conjunction with `withSpring`.
5320
5321### Reference
5322
5323```typescript
5324import { withClamp } from "react-native-reanimated"
5325
5326function App() {
5327 sv.value = withClamp({ min: -1, max: 1 }, withSpring(0))
5328 // ...
5329}
5330```
5331
5332#### Arguments
5333
5334##### `config`
5335
5336An object containing the following properties:
5337
5338|Name|Type|Description|
5339|-|-|-|
5340|min|number|Optional. The lowest value your animation can reach.|
5341|max|number|Optional. The highest value your animation can reach.|
5342
5343##### `animation`
5344
5345The spring animation you wish to clamp.
5346
5347```typescript
5348const clampedStyleWithDelay = useAnimatedStyle(() => {
5349 return {
5350 width: withClamp({ min: 0, max: 100 }, withSpring(randomWidth.value)),
5351 }
5352})
5353```
5354
5355#### Returns
5356
5357`withClamp` returns an animation object. This can be directly assigned to a shared value or used as a style value in `useAnimatedStyle`.
5358
5359|Platform|Supported|
5360|-|-|
5361|Android|✅|
5362|iOS|✅|
5363|Web|✅|
5364
5365## Logger configuration
5366
5367Reanimated provides warnings to highlight potential misuses of its API, such as altering shared values during component re-renders. These logs can be adjusted in verbosity.
5368
5369By default, the logger configuration requires no setup and displays all warnings and errors. To customize this behavior, use the `configureReanimatedLogger` function.
5370
5371### Reference
5372
5373To alter the default Reanimated logger settings, import `configureReanimatedLogger` from `react-native-reanimated` and invoke it with your desired configuration:
5374
5375```typescript
5376import {
5377 configureReanimatedLogger,
5378 ReanimatedLogLevel,
5379} from "react-native-reanimated"
5380
5381// Default configuration example
5382configureReanimatedLogger({
5383 level: ReanimatedLogLevel.warn,
5384 strict: true, // Strict mode is enabled by default
5385})
5386```
5387
5388#### Configuration Options
5389
5390- **`level`:** Specifies the minimum log level to display using a value from `ReanimatedLogLevel`.
5391
5392- **`strict`:** A boolean that toggles strict mode. Enabling it results in additional warnings to help identify potential code issues.
5393
5394### Remarks
5395
5396- The logger configuration is global, affecting all Reanimated warnings and errors. It cannot be configured on a per-file or per-component basis.
5397
5398- Call `configureReanimatedLogger` before creating any Reanimated animations, typically in the root file of your application.
5399
5400- This function is intended for app developers. Library creators using Reanimated should avoid including this call in their source code to prevent overriding users' configurations with the default settings.
5401
5402### Platform Compatibility
5403
5404|Android|iOS|Web|
5405|-|-|-|
5406|✅|✅|✅|
5407
5408## React Native Reanimated: ReducedMotionConfig
5409
5410**Version:** 3.x
5411
5412### Overview
5413
5414The `ReducedMotionConfig` component allows you to modify the behavior of animations based on a device's reduced motion accessibility setting. By default, it disables all animations when this setting is enabled. You can customize this behavior according to your specific needs. For more information about Accessibility and `useReducedMotion`, refer to Reanimated documentation.
5415
5416> **Caution:** The new configuration will be applied globally across the entire application.
5417
5418### Reference
5419
5420```typescript
5421import { ReducedMotionConfig, ReduceMotion } from 'react-native-reanimated';
5422
5423function App() {
5424 return (
5425 // ...
5426 <ReducedMotionConfig mode={ReduceMotion.Never} />
5427 // ...
5428 );
5429}
5430```
5431
5432#### Arguments
5433
5434##### `mode`
5435
5436This parameter determines how animations should respond to the device's reduced motion accessibility setting:
5437
5438- **`ReduceMotion.System`:** Adjusts animation behavior based on the device's reduced motion setting. Animations are disabled when this setting is enabled; otherwise, they remain active.
5439
5440- **`ReduceMotion.Always`:** Consistently disables animations, regardless of the device's accessibility configuration.
5441
5442- **`ReduceMotion.Never`:** Ensures that animations remain enabled at all times.
5443
5444### Platform Compatibility
5445
5446|Android|iOS|Web|
5447|-|-|-|
5448|✅|✅|✅|
5449
5450- Reference
5451 - Arguments
5452- Example
5453- Platform compatibility
5454
5455## Worklets
5456
5457Worklets are short-running JavaScript functions that execute on the UI thread, enabling efficient style calculations and event reactions. Reanimated leverages worklets for these tasks.
5458
5459### Creating Worklets
5460
5461To define a custom worklet, use the `'worklet';` directive at the start of your function:
5462
5463```typescript
5464function myWorklet() {
5465 "worklet"
5466 console.log("Hello from a worklet")
5467}
5468```
5469
5470The Reanimated Babel Plugin identifies functions marked with `'worklet'`, transforming them into serializable objects—a process known as workletization. These objects can then be executed on the UI thread.
5471
5472### Automatic Workletization
5473
5474When using Reanimated and Gesture Handler, code is typically automatically workletized and executed on the UI thread:
5475
5476```typescript
5477import { useAnimatedStyle } from "react-native-reanimated"
5478
5479function App() {
5480 const style = useAnimatedStyle(() => {
5481 // Executed on the UI thread
5482 return { opacity: 0.5 }
5483 })
5484}
5485```
5486
5487### Manual Worklet Execution
5488
5489To manually schedule worklet execution, use `runOnUI`:
5490
5491```typescript
5492function myWorklet() {
5493 "worklet"
5494 console.log("Hello from the UI thread")
5495}
5496
5497function onPress() {
5498 runOnUI(myWorklet)()
5499}
5500```
5501
5502Arguments can be passed to worklets as follows:
5503
5504```typescript
5505function myWorklet(greeting: string) {
5506 "worklet"
5507 console.log(`${greeting} from the UI thread`)
5508}
5509
5510function onPress() {
5511 runOnUI(myWorklet)("Howdy")
5512}
5513```
5514
5515### Worklet Closures
5516
5517Worklets are closures, allowing them to access variables declared outside their scope. Only referenced variables are captured:
5518
5519```typescript
5520const width = 135.5
5521
5522function otherWorklet() {
5523 "worklet"
5524 console.log("Captured width is", width)
5525}
5526```
5527
5528Avoid capturing large objects within worklets to prevent performance issues:
5529
5530```typescript
5531const theme = {...}; // Large object
5532
5533function myWorklet() {
5534 'worklet';
5535 console.log(theme.color); // 🚨 Captures entire `theme` object
5536}
5537```
5538
5539To mitigate this, assign the needed property to a separate variable:
5540
5541```typescript
5542const theme = {...};
5543const color = theme.color;
5544
5545function myWorklet() {
5546 'worklet';
5547 console.log(color); // ✅ Captures only `color`
5548}
5549```
5550
5551### Returning Data
5552
5553Worklets can return data within the same thread:
5554
5555```typescript
5556function returningWorklet() {
5557 "worklet"
5558 return "I'm back" // On the UI thread
5559}
5560
5561function someWorklet() {
5562 "worklet"
5563 const what = returningWorklet() // Still on the UI thread
5564 console.log("On the UI thread, other worklet says", what)
5565}
5566```
5567
5568### Data Sharing Between Threads
5569
5570Use shared values to pass data between the UI and JS threads:
5571
5572```typescript
5573import { useSharedValue } from "react-native-reanimated"
5574
5575function App() {
5576 const width = useSharedValue(100)
5577
5578 function myWorklet() {
5579 "worklet"
5580 width.value += 50
5581 }
5582
5583 useEffect(() => {
5584 console.log(width.value) // Accessible on both JS and UI threads
5585 }, [])
5586}
5587```
5588
5589### Running Functions on the JS Thread
5590
5591Use `runOnJS` to execute functions from the UI thread, often for non-worklet functions or React state updates:
5592
5593```typescript
5594import { router } from "expo-router"
5595import { Gesture } from "react-native-gesture-handler"
5596
5597function App() {
5598 const tap = Gesture.Tap().onEnd(() => {
5599 // Worklet context
5600 runOnJS(router.back)()
5601 })
5602}
5603```
5604
5605Ensure functions passed to `runOnJS` are defined in the JavaScript thread scope:
5606
5607```typescript
5608function App() {
5609 const tap = Gesture.Tap().onEnd(() => {
5610 // myFunction is defined on the UI thread 🚨
5611 const myFunction = () => {}
5612 runOnJS(myFunction)() // 💥 Error
5613 })
5614}
5615```
5616
5617### Custom Worklet Runtimes
5618
5619Worklets can operate in custom runtimes beyond Reanimated's default. Libraries like VisionCamera and LiveMarkdown create their own worklet environments.
5620
5621Create your own worklet runtime using `createWorkletRuntime`.
5622
5623## Accessibility
5624
5625This section discusses how Reanimated enhances accessibility in animations, particularly through its reduced motion functionality. This feature ensures a smoother experience for users with motion sensitivities or those who prefer less movement.
5626
5627The reduced motion configuration allows you to define how animations should respond to the system's reduced motion setting. For any animation, the value can be set as follows:
5628
5629- `ReduceMotion.System`: Adjusts the animation based on whether the device's reduced motion accessibility setting is activated. If enabled, the animation is disabled; otherwise, it remains active.
5630- `ReduceMotion.Always`: Consistently disables the animation, regardless of the device's accessibility configuration.
5631- `ReduceMotion.Never`: Ensures that the animation remains enabled at all times.
5632
5633By default, all animations are configured with `ReduceMotion.System`.
5634
5635### Reduced Motion in Animations
5636
5637```typescript
5638import { withDelay, withTiming } from "react-native-reanimated"
5639
5640function App() {
5641 sv1.value = withTiming(0, { reduceMotion: ReduceMotion.System })
5642 sv2.value = withDelay(
5643 1000,
5644 withTiming(toValue, { duration }),
5645 ReduceMotion.System
5646 )
5647 // ...
5648}
5649```
5650
5651When reduced motion is enabled:
5652
5653- `withSpring` and `withTiming` return the `toValue` immediately.
5654- `withDecay` returns the current value immediately, considering the clamp parameter.
5655- `withDelay` initiates the next animation immediately.
5656- `withRepeat`:
5657 - If `numberOfReps` is infinite or even and the animation is reversed, then the repeated animation does not start.
5658 - Otherwise, the repeated animation runs once.
5659- `withSequence` exclusively starts animations that have reduced motion disabled.
5660
5661Higher-order animations pass the configuration to their children only if the children haven't been configured by the user. For example:
5662
5663This animation will instantaneously reach the `toValue`:
5664
5665```typescript
5666import { withDelay, withTiming } from "react-native-reanimated"
5667
5668function App() {
5669 sv.value = withDelay(
5670 1000,
5671 withTiming(toValue, { duration }),
5672 ReduceMotion.Always
5673 )
5674 // ...
5675}
5676```
5677
5678This animation will execute as usual even if reduced motion is enabled on the device:
5679
5680```typescript
5681import { withDelay, withTiming } from "react-native-reanimated"
5682
5683function App() {
5684 sv.value = withDelay(
5685 1000,
5686 withTiming(toValue, { duration }),
5687 ReduceMotion.Never
5688 )
5689 // ...
5690}
5691```
5692
5693And here `withTiming` will be executed as usual and without delay:
5694
5695```typescript
5696import { withDelay, withTiming } from "react-native-reanimated"
5697
5698function App() {
5699 sv.value = withDelay(
5700 1000,
5701 withTiming(toValue, { duration, reduceMotion: ReduceMotion.Never }),
5702 ReduceMotion.Always
5703 )
5704 // ...
5705}
5706```
5707
5708### Reduced Motion in Layout Animations
5709
5710```typescript
5711import { BounceIn } from "react-native-reanimated"
5712
5713function App() {
5714 const entering = BounceIn.reduceMotion(ReduceMotion.System)
5715 // ...
5716}
5717```
5718
5719When reduced motion is enabled:
5720
5721- Entering, keyframe, and layout animations instantaneously reach their endpoints.
5722- Exiting animations and shared transitions are omitted.
5723
5724### `useReducedMotion`
5725
5726This hook returns a boolean indicating whether the reduced motion setting was enabled when the app started. It can be used in conjunction with other libraries or to conditionally display animations that are less intrusive.
5727
5728```typescript
5729import { BounceIn } from "react-native-reanimated"
5730
5731function App() {
5732 const reduceMotion = useReducedMotion()
5733 const entering = reduceMotion
5734 ? FadeIn.reduceMotion(ReduceMotion.Never)
5735 : BounceIn
5736 // ...
5737}
5738```
5739
5740## Glossary of terms
5741
5742### Animated Component
5743
5744Animated components are those that can be animated using Reanimated. The library includes built-in components such as `Animated.View`, `Animated.Text`, and `Animated.ScrollView`.
5745
5746```typescript
5747import Animated from 'react-native-reanimated';
5748
5749function App() {
5750 return (
5751 <Animated.View
5752 style={{
5753 width: 100,
5754 height: 100,
5755 backgroundColor: 'violet',
5756 }}
5757 />
5758 );
5759}
5760```
5761
5762For components not included in Reanimated, you can make their props and styles animatable by wrapping them with `createAnimatedComponent`:
5763
5764```typescript
5765import Animated from "react-native-reanimated"
5766import { Circle } from "react-native-svg"
5767
5768const AnimatedCircle = Animated.createAnimatedComponent(Circle)
5769```
5770
5771### Shared Value
5772
5773Shared values are essential for animations in Reanimated. They are defined using the `useSharedValue` hook and accessed or modified via their `.value` property.
5774
5775```typescript
5776import { useSharedValue } from "react-native-reanimated"
5777
5778function App() {
5779 const sv = useSharedValue(0)
5780
5781 const handlePress = () => {
5782 sv.value += 10
5783 }
5784
5785 // rest of your glamorous code ✨
5786}
5787```
5788
5789Shared values can store any type and automatically synchronize data between the JavaScript thread and the UI thread.
5790
5791### Animatable Value
5792
5793An animatable value is a type that can be used for animations, including numbers, strings, and arrays of numbers. Strings in specific formats like `"10deg"`, `"21%"`, or colors such as `"#ffaabb"` or `"rgba(100, 200, 100, 0.7)"` are also animatable.
5794
5795### Animation Function
5796
5797Animation functions define how animations should behave. Reanimated provides three built-in animation functions:
5798
5799- `withSpring`: Creates spring-based animations.
5800- `withTiming`: Creates duration and easing-based animations.
5801- `withDecay`: Mimics motion with a given deceleration rate.
5802
5803These can be combined with modifiers for complex animations.
5804
5805### Animation Modifier
5806
5807Animation modifiers customize animations. Known as higher-order animations, Reanimated includes:
5808
5809- `withDelay`: Adds a delay before the animation starts.
5810- `withRepeat`: Repeats an animation a specified number of times.
5811- `withSequence`: Chains animations sequentially.
5812- `withClamp`: Limits animation boundaries to a specific range.
5813
5814### Animation Object
5815
5816An animation object is returned from animation functions and modifiers, containing the current state of the animation. It includes start and end conditions and an `onFrame` function for calculating each frame's state.
5817
5818When passed to a shared value, it is treated as an animatable value:
5819
5820```typescript
5821sv.value = withSpring(100)
5822```
5823
5824### Animations in Inline Styling
5825
5826Shared values can be directly used in the `style` property without `useAnimatedStyle`.
5827
5828Example:
5829
5830```typescript
5831function App() {
5832 const width = useSharedValue(100);
5833
5834 return <Animated.View style={{ width }} />;
5835}
5836```
5837
5838### Layout Animation Modifier
5839
5840Layout animation modifiers customize layout animations. Example usage:
5841
5842```typescript
5843<Animated.View entering={FadeOutLeft.duration(500).easing(Easing.ease)} />
5844```
5845
5846Built-in modifiers include:
5847
5848- `.duration(durationMs: number)`: Sets the animation length in milliseconds.
5849- `.easing(easingFunction: EasingFunction)`: Defines the animation curve.
5850- `.springify()`: Enables spring-based animations.
5851- `.damping(value: number)`: Controls how quickly a spring stops moving.
5852- `.withCallback(callback: (finished: boolean) => void)`: Triggers after the animation ends.
5853
5854### Worklet
5855
5856Worklets are short-running JavaScript functions executed on the UI thread. They can also run on the JavaScript thread like regular functions.
5857
5858Code is often automatically workletized and runs on the UI thread by default:
5859
5860```typescript
5861const style = useAnimatedStyle(() => {
5862 console.log("Running on the UI thread")
5863 return { opacity: 0.5 }
5864})
5865```
5866
5867Custom worklets can be created using the `"worklet";` directive:
5868
5869```typescript
5870function myWorklet() {
5871 "worklet"
5872 console.log("Running on the UI thread")
5873}
5874```
5875
5876Use `runOnUI` to manually execute worklets on the UI thread:
5877
5878```typescript
5879function myWorklet(greeting) {
5880 "worklet"
5881 console.log(`${greeting} from the UI thread`)
5882}
5883
5884function onPress() {
5885 runOnUI(myWorklet)("Howdy")
5886}
5887```
5888
5889### To Workletize
5890
5891Converts a JavaScript function into an object that can be serialized and executed on the UI thread. Functions marked with `"worklet";` are automatically workletized by the Reanimated Babel plugin.
5892
5893### JavaScript Thread
5894
5895The JavaScript thread handles code execution in the app, serving as the primary location for React Native app code execution.
5896
5897### UI Thread
5898
5899The UI thread manages user interface updates and is also known as the Main thread. More information can be found in the Threading model article of the official React Native documentation.
5900
5901### Reanimated Babel Plugin
5902
5903This plugin automatically workletizes certain functions used with Reanimated, reducing boilerplate code. Details are available in the Reanimated Babel plugin README.
5904
5905## Entering/Exiting animations
5906
5907The provided content outlines a comprehensive guide for using various animations in React Native with the `react-native-reanimated` library. Below is a structured summary of the key points and features:
5908
5909#### Overview
5910
5911- **Library**: `react-native-reanimated`
5912- **Purpose**: To create smooth, performant animations on Android, iOS, and Web platforms.
5913- **Animations Covered**:
5914 - Pinch
5915 - Pinch Zoom
5916 - Pinch Rotate
5917 - Pinch Scale
5918 - Pinch Translate
5919 - Pinch X
5920 - Pinch Y
5921 - PinchXY
5922 - PinchZoomRotate
5923 - PinchZoomScale
5924 - PinchZoomTranslate
5925 - PinchZoomX
5926 - PinchZoomY
5927 - PinchZoomXY
5928 - PinchZoomRotateScale
5929 - PinchZoomRotateTranslate
5930 - PinchZoomRotateX
5931 - PinchZoomRotateY
5932 - PinchZoomRotateXY
5933 - PinchZoomScaleTranslate
5934 - PinchZoomScaleX
5935 - PinchZoomScaleY
5936 - PinchZoomScaleXY
5937 - PinchZoomTranslateX
5938 - PinchZoomTranslateY
5939 - PinchZoomTranslateXY
5940 - PinchZoomRotateScaleTranslate
5941 - PinchZoomRotateScaleX
5942 - PinchZoomRotateScaleY
5943 - PinchZoomRotateScaleXY
5944 - PinchZoomRotateTranslateX
5945 - PinchZoomRotateTranslateY
5946 - PinchZoomRotateTranslateXY
5947 - PinchZoomScaleTranslateX
5948 - PinchZoomScaleTranslateY
5949 - PinchZoomScaleTranslateXY
5950 - PinchZoomRotateScaleTranslateX
5951 - PinchZoomRotateScaleTranslateY
5952 - PinchZoomRotateScaleTranslateXY
5953 - Other animations like Bounce, Fade, Flip, etc.
5954
5955#### Animation Configuration
5956
5957##### Time-based Modifiers
5958
5959- **Function**: `withTiming`
5960- **Customization**:
5961 - `.easing(easingFunction: EasingFunction)`: Defines the animation curve. Default is `Easing.inOut(Easing.quad)`.
5962 - Note: These modifiers do not affect spring animations.
5963
5964##### Spring-based Modifiers
5965
5966- **Function**: `withSpring`
5967- **Customization**:
5968 - `.springify()`: Enables spring-based configuration.
5969 - `.damping(value: number)`: Controls how quickly the spring stops. Default is `10`.
5970 - `.mass(value: number)`: Represents the weight of the spring. Lower values make animations faster. Default is `1`.
5971 - `.stiffness(value: number)`: Determines bounciness. Default is `100`.
5972 - `.overshootClamping(value: boolean)`: Prevents bouncing over the target position. Default is `false`.
5973 - `.restDisplacementThreshold(value: number)`: Displacement threshold for snapping to the final position without oscillations. Default is `0.001`.
5974 - `.restSpeedThreshold(value: number)`: Speed threshold for snapping to the final position without oscillations. Default is `2`.
5975
5976##### Common Modifiers
5977
5978- **Customization**:
5979 - `.duration(durationMs: number)`: Length of the animation in milliseconds. Default is `300`.
5980 - `.delay(durationMs: number)`: Delay before starting the animation. Default is `0`.
5981 - `.randomDelay()`: Randomizes delay between `0` and provided value, defaulting to `1000ms` if not specified.
5982 - `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts animation based on device's reduced motion settings.
5983 - `.withInitialValues(values: StyleProps)`: Overrides initial configuration of the animation.
5984 - `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
5985
5986#### Platform Compatibility
5987
5988- **Android**: Supported
5989- **iOS**: Supported
5990- **Web**: Supported
5991
5992This guide provides developers with the tools to create and customize animations effectively across multiple platforms using `react-native-reanimated`.
5993
5994## Troubleshooting React Native Reanimated Build Issues on Windows
5995
5996This guide outlines basic troubleshooting steps for resolving issues encountered when building React Native apps with Reanimated for Android devices on a Windows host machine. Common errors include:
5997
5998- `Execution failed for task ':react-native-reanimated:buildCMakeDebug[x86_64]'`
5999- `Execution failed for task ':react-native-reanimated:buildCMakeRelWithDebInfo[arm64-v8a]'`
6000- `Task :react-native-reanimated:buildCMakeDebug[x86_64] FAILED`
6001- `C/C++: ninja: error: mkdir(...): No such file or directory`
6002- `C++ build system [build] failed while executing`
6003- `Picked up _JAVA_OPTIONS`
6004
6005### What Not to Do
6006
6007If you encounter any of the above errors, avoid these actions:
6008
6009#### ❌ Avoid Disabling New Architecture
6010
6011Starting from React Native 0.76, New Architecture is enabled by default. Manually disabling it in `gradle.properties` does not resolve issues and merely delays them since legacy architecture will be phased out.
6012
6013#### ❌ Avoid Downgrading Android Gradle Plugin (AGP)
6014
6015Do not modify the AGP version in `gradle.properties`. Use the version specified in the official app template to prevent version conflicts and unsupported features.
6016
6017#### ❌ Avoid Downgrading Reanimated or Other Dependencies
6018
6019Downgrading increases technical debt. Newer versions of Reanimated include bug fixes and stability improvements. Always use the latest supported version, and consider upgrading all dependencies rather than downgrading them.
6020
6021#### ❌ Avoid Posting Duplicate "Same Issue" Comments
6022
6023Before reporting an error, search for similar issues on platforms like GitHub or Stack Overflow. Instead of posting duplicate comments, add a reaction to the original issue to indicate its impact.
6024
6025### Recommended Actions
6026
6027#### ✅ Ensure Correct Environment Setup
6028
6029Follow all instructions in Set Up Your Environment. Run `npx react-native doctor` to identify any problems. Restart your terminal, IDE, or computer if changes have been made.
6030
6031#### ✅ Use Compatible Reanimated Version
6032
6033Use the latest supported version of Reanimated based on your app setup:
6034
6035- **Expo SDK**: Match major and minor versions with Expo SDK.
6036 - Example: Expo SDK 52 supports `~3.16.x`. Update to the latest patch, e.g., `3.16.7`.
6037
6038|Expo SDK Version|Reanimated Version|
6039|-|-|
6040|`52`|`~3.16.1`|
6041|`51`|`~3.10.1`|
6042|`50`|`~3.6.2`|
6043
6044- **Expo Prebuild or React Native without Framework**: Use a version compatible with your React Native version according to the Compatibility table.
6045
6046#### ✅ Use Appropriate CMake Version
6047
6048Ensure you use CMake `3.22.1` or newer. Customize the version using the `CMAKE_VERSION` environment variable, e.g., `set CMAKE_VERSION=3.31.1`. If unset, default is `3.22.1`.
6049
6050#### ✅ Use Appropriate Ninja Version
6051
6052Use Ninja `1.12.0` or newer (latest is `1.12.1`) as older versions may not handle long paths correctly.
6053
6054#### ✅ Use Compatible Android NDK Version
6055
6056Match the NDK version with that used in the official app template. It should be installed automatically during app build.
6057
6058#### ✅ Unset `_JAVA_OPTIONS`
6059
6060Unsetting this environment variable can resolve certain errors and allow builds to pass.
6061
6062#### ✅ Enable Long Paths Support in Windows Registry
6063
6064Follow instructions to enable long paths support on Windows.
6065
6066#### ✅ Avoid Whitespace in Project Path
6067
6068Paths with spaces may cause issues. Move projects to directories without whitespace, e.g., `D:\Mobile Apps\MyAwesomeProject`.
6069
6070#### ✅ Ensure Short Project Path
6071
6072Avoid paths longer than 240 characters. Move or clone the project to a shorter path, e.g., `D:\AwesomeProject`.
6073
6074#### ✅ Remove or Invalidate Caches
6075
6076Clear compilation artifacts in directories like:
6077
6078- `android\build`
6079- `android\.cxx`
6080- `android\.gradle`
6081- `node_modules\react-native-reanimated\android\build`
6082
6083Invalidate Android Studio caches (File → Invalidate Caches…).
6084
6085#### ⚠️ Persistent Issues
6086
6087If problems persist after following these steps, submit an issue in the repository with full build logs and a minimal reproducible example.
6088
6089## Compatibility Table
6090
6091### Currently Supported React Native Versions (Paper)
6092
6093|Version|0.63|0.64|0.65|0.66|0.67|0.68|0.69|0.70|0.71|0.72|0.73|0.74|0.75|0.76|0.77|0.78|0.79|0.80|
6094|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
6095|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
6096|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
6097|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
6098|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
6099|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
6100|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
6101|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
6102|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
6103|3.6.x – 3.8.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|
6104|3.5.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
6105|3.3.x – 3.4.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
6106|3.0.x – 3.2.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
6107|2.14.x – 2.17.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
6108|2.11.x – 2.13.x|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|
6109|2.10.x|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|
6110|2.5.x – 2.9.x|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|
6111|2.3.x – 2.4.x|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|no|
6112
6113**Note:** Reanimated 2 will not receive support for the newest React Native versions. To access the latest features and updates, upgrade to Reanimated 3.
6114
6115### Supported React Native Versions on the New Architecture (Fabric)
6116
6117To use Reanimated with the experimental New Architecture, update the package to at least version 3.0.0. Due to numerous breaking changes related to the New Architecture in each React Native version, as a rule of thumb, Reanimated supports the latest stable version of React Native.
6118
6119Reanimated supports bridgeless mode.
6120
6121|Version|0.63|0.64|0.65|0.66|0.67|0.68|0.69|0.70|0.71|0.72|0.73|0.74|0.75|0.76|0.77|0.78|0.79|0.80|
6122|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
6123|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
6124|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
6125|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
6126|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
6127|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
6128|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
6129|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
6130|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
6131|3.6.x – 3.8.x|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|no|no|
6132|3.1.x – 3.5.x|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|
6133|3.0.x|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|no|
6134
6135## useSharedValue
6136
6137`useSharedValue` is a hook that allows you to define shared values within your components.
6138
6139### Reference
6140
6141```typescript
6142import { useSharedValue } from "react-native-reanimated"
6143
6144function App() {
6145 const sv = useSharedValue(100)
6146
6147 // Accessing the shared value
6148 console.log(sv.value)
6149
6150 // Modifying the shared value
6151 sv.value += 50
6152}
6153```
6154
6155#### Arguments
6156
6157##### `initialValue`
6158
6159The initial value to store in the shared value. It can be any JavaScript type such as `number`, `string`, or `boolean`, and also includes data structures like `array` and `object`.
6160
6161#### Returns
6162
6163`useSharedValue` returns a shared value initialized with the provided `initialValue`. You can access this stored data using its `value` property or through `get` and `set` methods.
6164
6165##### React Compiler Support
6166
6167When utilizing the React Compiler, avoid directly accessing or modifying the `value` property. Instead, use the `get` and `set` methods as they are compliant with React Compiler standards.
6168
6169```typescript
6170function App() {
6171 const sv = useSharedValue(100)
6172
6173 const animatedStyle = useAnimatedStyle(() => {
6174 "worklet"
6175 return { width: sv.get() * 100 }
6176 })
6177
6178 const handlePress = () => {
6179 sv.set((value) => value + 1)
6180 }
6181}
6182```
6183
6184### Remarks
6185
6186- Avoid reading or modifying the shared value during a component's render. Accessing the `value` property or using `get`/`set` methods is considered a side-effect, which violates React's Rules of Render.
6187
6188- Changes to `sv.value` will update styles and synchronize the shared value across threads without triggering a typical React re-render since it's a plain JavaScript object.
6189
6190- Reading `sv.value` on the JavaScript thread may block until the value is fetched from the UI thread. This can be negligible, but if the UI thread is busy or values are read multiple times, synchronization delays might increase.
6191
6192- Changes to `sv.value` occur synchronously on the UI thread, while updates on the JavaScript thread are asynchronous. Thus, logging `value` immediately after a change will show the previous value.
6193
6194```typescript
6195function App() {
6196 const sv = useSharedValue(100) // initially set to 100
6197
6198 sv.value += 50 // modifying the shared value
6199
6200 console.log(sv.value) // logs 100 due to asynchronous update on JS thread
6201}
6202```
6203
6204- Avoid destructuring assignment with shared values. While valid in JavaScript, it prevents Reanimated from maintaining reactivity.
6205
6206```typescript
6207function App() {
6208 let { value } = sv // avoid this pattern
6209
6210 console.log(value) // reading is fine
6211
6212 value += 50 // does not update styles
6213}
6214```
6215
6216- When storing objects in a shared value, ensure to reassign the entire object rather than modifying its properties individually.
6217
6218```typescript
6219function App() {
6220 const sv = useSharedValue({ x: 0, y: 0 })
6221
6222 sv.value.x = 50 // loses reactivity
6223
6224 sv.value = { x: 50, y: 0 } // correct approach
6225}
6226```
6227
6228- For large arrays or complex objects in a shared value, use the `.modify` method to alter the existing value without creating a new one.
6229
6230```typescript
6231function App() {
6232 const sv = useSharedValue([1, 2, 3])
6233
6234 sv.value.push(1000) // loses reactivity
6235
6236 sv.value = [...sv.value, 1000] // creates a new copy
6237
6238 sv.modify((value) => {
6239 "worklet"
6240 value.push(1000) // correct approach
6241 return value
6242 })
6243}
6244```
6245
6246### Platform Compatibility
6247
6248|Android|iOS|Web|
6249|-|-|-|
6250|✅|✅|✅|
6251
6252## Contributing
6253
6254Thank you for considering contributing to Reanimated. Contributions can range from triaging issues and enhancing documentation to reviewing Pull Requests and submitting code changes.
6255
6256### Ways to Contribute
6257
62581. **Handling Open Issues**: Assist by providing detailed descriptions and reproducible examples for existing issues, which helps other contributors understand and address them more efficiently.
6259
62601. **Documentation Assistance**: Improve the documentation by correcting spelling and grammar or expanding explanations. You can also help update outdated pages from Reanimated v2 to the current version. For significant changes, edit locally using Docusaurus and GitHub Pages.
6261
62621. **Reviewing Pull Requests**: Review submitted Pull Requests to identify potential issues or bugs that may have been overlooked, ensuring high-quality contributions.
6263
62641. **Code Contributions**: Submit code through Pull Requests to address issues, fix bugs, or introduce new features. Beginners can start with "good first issue" tasks on GitHub.
6265
6266#### Repository Structure
6267
6268The Reanimated repository is organized as follows:
6269
6270```
6271├── apps
6272│ ├── common-app // Shared source for example apps
6273│ ├── paper-example // React Native app using Old Architecture
6274│ ├── fabric-example // React Native app using New Architecture
6275│ ├── macos-example // React Native for MacOS wrapper
6276│ ├── next-example // Next.js wrapper
6277│ ├── tvos-example // React Native for TVOS wrapper
6278│ └── web-example // React Native for Web wrapper
6279└── packages
6280 ├── docs-reanimated // Documentation source
6281 ├── eslint-plugin-reanimated // ESLint plugin source
6282 └── react-native-reanimated
6283 ├── android // Android native code
6284 ├── apple // iOS native code
6285 ├── Common // Shared C++ code
6286 ├── scripts // CI pipeline scripts
6287 ├── src // Reanimated JS source
6288 └── plugin // Babel plugin source
6289```
6290
6291### Handling Open Issues
6292
6293Providing detailed descriptions and reproducible examples for issues can significantly aid other contributors. Ensure that issues include:
6294
6295- A cloneable repository.
6296- Clear reproduction steps.
6297- Comprehensive descriptions.
6298- Relevant stack traces.
6299
6300If these details are missing, consider asking the issue owner or providing them yourself to facilitate quicker resolutions.
6301
6302### Documentation Assistance
6303
6304Improving documentation is a straightforward way to contribute. The Reanimated docs use Docusaurus and GitHub Pages. For minor edits, click **Edit this page** at the bottom of most pages. For more complex changes:
6305
63061. Clone `react-native-reanimated`.
63071. Navigate to `packages/docs-reanimated`.
63081. Run `yarn && yarn start` to preview changes locally.
6309
6310#### Documentation Structure
6311
6312Maintain a consistent structure for clarity and ease of navigation:
6313
63141. **Introduction**: Briefly describe the feature.
63151. **Reference**: Provide simple usage examples with type definitions.
63161. **Arguments**: Detail accepted arguments.
63171. **Returns**: Explain returned values.
63181. **Example**: Include videos, GIFs, or interactive demos in both light and dark modes.
63191. **Remarks**: Highlight non-obvious details like platform-specific quirks.
63201. **Platform Compatibility**: Specify supported platforms.
6321
6322#### Writing Style Guide
6323
6324- Use active voice for clarity (e.g., "The function receives the arguments").
6325- Write short, clear sentences to aid comprehension.
6326- Organize information into lists for better readability.
6327- Avoid acronyms unless globally recognized (e.g., UI, API).
6328- Use contractions for a conversational tone.
6329
6330#### Embedding Interactive Examples
6331
6332Use the `InteractiveExample` component with `src` and `component` props to create engaging examples. For videos:
6333
6334```typescript
6335import AnimatedKeyboardSrc from '!!raw-loader!@site/src/examples/AnimatedKeyboard';
6336
6337<InteractiveExample
6338 src={AnimatedKeyboardSrc}
6339 component={
6340 <ThemedVideo
6341 center
6342 width={300}
6343 sources={{
6344 light: '/recordings/useAnimatedKeyboard_light.mov',
6345 dark: '/recordings/useAnimatedKeyboard_dark.mov',
6346 }}
6347 />
6348 }
6349/>;
6350```
6351
6352For interactive components:
6353
6354```typescript
6355import DecayTrain from '@site/src/examples/DecayTrain';
6356import DecayTrainSrc from '!!raw-loader!@site/src/examples/DecayTrain';
6357
6358<InteractiveExample
6359 src={DecayTrainSrc}
6360 component={<DecayTrain />}
6361 label="Grab and drag the train"
6362/>;
6363```
6364
6365### Contributing Code
6366
6367Submit Pull Requests to address issues or introduce new features. Start with "good first issue" tasks if you're new to open-source contributions.
6368
6369#### Working with Android
6370
63711. Install dependencies: `yarn && yarn build`.
63721. Navigate to `apps/paper-example` and run `yarn start`.
63731. Open the project in Android Studio at `react-native-reanimated/apps/paper-example/android`.
6374
6375#### Working with iOS
6376
63771. Install dependencies: `yarn && yarn build`.
63781. Run `cd apps/paper-example/ios && bundle install && bundle exec pod install`.
63791. Start Metro bundler: `cd apps/paper-example && yarn start`.
63801. Open the project in Xcode at `react-native-reanimated/apps/paper-example/ios/ReanimatedExample.xcworkspace`.
6381
6382#### Preparing a Pull Request
6383
6384When ready, open a Pull Request using the provided template:
6385
63861. **Summary**: Link relevant issues and describe your changes.
63871. **Test Plan**: Provide instructions for testing, including code from `EmptyExample` if applicable.
6388
6389#### Testing Changes Locally
6390
6391To test changes in your project, create a patch with `git diff` or point to a specific commit in `package.json`.
6392
6393Thank you for contributing! 🎉
6394
6395## Debugging worklets
6396
6397### Overview
6398
6399This document provides guidance on debugging Reanimated v2 worklets within React Native applications. Due to Reanimated's unique architecture and use of a secondary JavaScript runtime, traditional debugging methods may not function as expected. This article outlines compatible tools and their limitations.
6400
6401#### React Native Debugging Tools
6402
6403The following tools have been evaluated for compatibility with React Native apps using the Reanimated library:
6404
6405- **Chrome Debugger (React Native Debugger):** Utilizes a web worker in your browser to execute app JavaScript code, supporting all available runtimes in React Native.
6406
6407- **Chrome DevTools:** Connects to a remote JavaScript runtime, allowing code execution on the device. Note: Not compatible with JSC.
6408
6409- **Flipper (Hermes debugger):** Facilitates using Chrome DevTools and offers additional UI inspection tools.
6410
6411- **Safari DevTools:** Available only for iOS devices running JSC, similar in functionality to Chrome DevTools by connecting to a remote runtime.
6412
6413- **React Developer Tools:** A standalone app for debugging UI through an inspector, monitoring performance, and profiling the application.
6414
6415#### JS Context vs. UI Context
6416
6417Understanding the distinction between the JavaScript (JS) context and the User Interface (UI) context is crucial. Debugging the regular JS context remains unchanged with Reanimated; however, debugging the UI context specific to Reanimated can be challenging.
6418
6419#### Debugging Web Apps
6420
6421For web applications, standard browser tools or any preferred debugging tools can be used without issues when employing Reanimated on the web.
6422
6423### Compatibility Summary
6424
6425|Tool|Platform|JSC|Hermes|V8|
6426|-|-|-|-|-|
6427|Chrome Debugger|Android|⚛️ ✅¹|⚛️ ✅¹|⚛️ ✅¹|
6428||iOS|⚛️ ✅¹|⚛️ ✅¹|N/A|
6429|Chrome DevTools|Android|N/A|⚛️ ✅²|⚛️|
6430||iOS|N/A|⚛️ ✅²|N/A|
6431|Flipper (Hermes debugger)|Android|N/A|⚛️ ✅²|⚛️|
6432||iOS|N/A|⚛️ ✅²|N/A|
6433|Safari DevTools|Android|N/A|N/A|N/A|
6434||iOS|⚛️ ✅|N/A|N/A|
6435|React Developer Tools|Android|⚛️|⚛️|⚛️|
6436||iOS|⚛️|⚛️|N/A|
6437
6438¹ - Functions use web implementations, running worklets on the JS thread. Measure and Layout Animations are unavailable. ² - Experimental feature.
6439
6440#### Legend
6441
6442- ⚛️ ✅: Special features for React Native apps using Reanimated
6443- ⚛️: Standard functionality with no worklet debugging available
6444- N/A: Not applicable in React Native apps
6445
6446**Note:** Console logs will always appear in the primary JS runtime as `console.log` on the UI runtime is a wrapper around the JS runtime's function.
6447
6448### Tool-Specific Details
6449
6450#### Chrome Debugger
6451
6452|Platform|JSC|Hermes|V8|
6453|-|-|-|-|
6454|Android|⚛️ ✅|⚛️ ✅|⚛️ ✅|
6455|iOS|⚛️ ✅|⚛️ ✅|N/A|
6456
6457**Summary:** Functions use web implementations, running on the JS thread. Measure and Layout Animations are unavailable.
6458
6459#### Chrome DevTools
6460
6461|Platform|JSC|Hermes|V8|
6462|-|-|-|-|
6463|Android|N/A|⚛️ ✅²|⚛️|
6464|iOS|N/A|⚛️ ✅²|N/A|
6465
6466**Summary:** Both contexts can be debugged. This is an experimental feature.
6467
6468#### Flipper (Hermes Debugger)
6469
6470|Platform|JSC|Hermes|V8|
6471|-|-|-|-|
6472|Android|N/A|⚛️ ✅²|⚛️|
6473|iOS|N/A|⚛️ ✅²|N/A|
6474
6475**Summary:** Both contexts can be debugged. This is an experimental feature.
6476
6477#### Safari DevTools
6478
6479|Platform|JSC|Hermes|V8|
6480|-|-|-|-|
6481|Android|N/A|N/A|N/A|
6482|iOS|⚛️ ✅|N/A|N/A|
6483
6484**Summary:** Available only on iOS devices with the JSC engine. Worklet debugging is supported.
6485
6486#### React Developer Tools
6487
6488|Platform|JSC|Hermes|V8|
6489|-|-|-|-|
6490|Android|⚛️|⚛️|⚛️|
6491|iOS|⚛️|⚛️|N/A|
6492
6493**Summary:** Functions as expected, with profiler and layout inspector available.
6494
6495#### Additional Notes
6496
6497- **Console Logs:** Always appear in the primary JS runtime.
6498
6499- **Known Issues:** Include reload failures, breakpoint issues on iOS, unresponsive consoles without animations, and more. These do not affect release builds or debug builds where the debugger is disconnected during a reload.
6500
6501*Efforts are ongoing to enhance debugging experiences with Chrome DevTools and Flipper on Hermes.*