this repo has no description
at main 201 kB view raw
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.*