···627627628628***
629629630630-## Accessing and Managing Device Color Scheme
630630+## useColorScheme()
631631632632The `useColorScheme()` function provides a way to access and manage the device's current color scheme.
633633···809809810810These classes are used to define how the background of an element is clipped, with support limited to web browsers.
811811812812-## Responsive Design in Nativewind
812812+## Responsive Design
813813814814**Note:**\
815815The default theme of Nativewind is not specifically tailored for native devices. It currently employs breakpoints that are primarily intended for web applications.
816816817817Nativewind's approach to responsive design mirrors that of Tailwind CSS. For detailed information, please consult the official Tailwind CSS documentation.
818818819819-## remapProps Utility in Nativewind
819819+## remapProps
820820821821Nativewind offers a utility called `remapProps` to streamline the integration of third-party components that have multiple "style" props. This tool allows developers to map Tailwind CSS class names to these style props, enhancing ease of use and consistency.
822822···4263426342644264This configuration allows you to specify additional class attributes that Tailwind CSS will recognize and apply.
4265426542664266-```markdown
42674267-## Content Rules in Nativewind
42664266+## Content
4268426742694268Nativewind adheres to the same content configuration guidelines as Tailwind CSS. For detailed information and solutions to potential issues, consult the official Tailwind CSS documentation.
42704270-```
42714271-42724272-This reformatted markdown maintains the original message while ensuring clarity and conciseness for an AI context.
4273426942744270## Overflow
42754271···47054701}
47064702```
4707470347084708-## Usage
47044704+## Top / Right / Bottom / Left
4709470547104706For detailed information, please consult the Tailwind CSS documentation.
47114707
+46-50
out/llms-full-react-native-gesture-handler.txt
···22222323Software Mansion is a team of React Native Core Contributors and experts specializing in resolving various React Native challenges. Whether you need assistance with gestures, animations, or general development, we are here to help.
24242525-## Installation Guide for react-native-gesture-handler
2525+## Installation
26262727### Requirements
2828···176176177177Ensure each screen in your app is wrapped with `GestureHandlerRootView` as native navigation libraries map each screen to a separate root view.
178178179179-## Rotation Gesture
179179+## Rotation gesture
180180181181A continuous gesture capable of recognizing and tracking rotation movements. Activation occurs when fingers are placed on the screen and move in a specific manner.
182182···302302303303- **`pointerType`**: Type of pointer device, represented by the `PointerType` enum (`TOUCH`, `STYLUS`, `MOUSE`, `KEY`, `OTHER`).
304304305305-## Pinch Gesture
305305+## Pinch gesture
306306307307A continuous gesture that recognizes pinch gestures, allowing for tracking the distance between two fingers to scale or zoom content. The gesture activates when fingers are placed on the screen and change their position. A callback can be used for continuous tracking of the pinch gesture, providing information about velocity, anchor (focal) point, and scale.
308308···629629}
630630```
631631632632-## Pan Gesture
632632+## Pan gesture
633633634634A pan gesture recognizes and tracks a continuous dragging motion. It activates when a finger touches the screen and moves beyond an initial distance.
635635···879879}
880880```
881881882882-## Gesture States and Events
882882+## Gesture states & events
883883884884Each gesture can be conceptualized as a "state machine." At any given moment, each handler instance is assigned a state that may change due to new touch events or specific conditions imposed by the touch system.
885885···959959- **`onPointerCancelled`**
960960 - Called when no further pointer information is available due to gesture completion or interruption. May involve multiple pointers due to event batching.
961961962962-## Handler State Overview
962962+## Handler State
963963964964Gesture handlers are conceptualized as "state machines," where each instance maintains an assigned state that can change due to new touch events or be altered by the touch system under specific conditions. There are six possible states for a gesture handler:
965965···1036103610371037Signifies the end of a gesture with touches indicating completion. The state transitions to `UNDETERMINED` after resetting.
1038103810391039-```markdown
10401040-# Legacy Gesture Handlers
10391039+## Legacy Gesture Handlers
1041104010421042-## Overview
10411041+### Overview
1043104210441043The legacy gesture handler API is scheduled for removal in upcoming versions of Gesture Handler. Users are encouraged to transition to the new gestures API. For detailed migration instructions, refer to the provided upgrading guide.
1045104410461046-## Cross-Handler Interactions
10451045+### Cross-Handler Interactions
1047104610481047The previous cross-handler interaction capabilities will be deprecated in future releases. Transitioning to the updated gestures API is recommended. Consult the upgrading guide for further details.
1049104810501050-## Common Handler Properties
10491049+### Common Handler Properties
1051105010521051Properties common across handlers in the old API are slated for removal. Users should adopt the new gestures API and refer to the upgrading guide for assistance.
1053105210541054-## Specific Gesture Handlers
10531053+### Specific Gesture Handlers
1055105410561056-### Pan
10551055+#### Pan
1057105610581057The pan gesture handler from the legacy API will be deprecated. Transitioning to the gestures API is advised. See the upgrading guide for more information.
1059105810601060-### Tap
10591059+#### Tap
1061106010621061The tap gesture handler in the old API will no longer be supported. Users should migrate to the new gestures API. Refer to the upgrading guide for guidance.
1063106210641064-### Long Press
10631063+#### Long Press
1065106410661065Long press functionality from the legacy API will be removed. Transitioning to the gestures API is recommended. Consult the upgrading guide for more details.
1067106610681068-### Rotation
10671067+#### Rotation
1069106810701069The rotation gesture handler in the old API will be deprecated. Migrating to the gestures API is advised. See the upgrading guide for further information.
1071107010721072-### Fling
10711071+#### Fling
1073107210741073Fling gesture handling from the legacy API will be removed. Users should transition to the new gestures API. Refer to the upgrading guide for assistance.
1075107410761076-### Pinch
10751075+#### Pinch
1077107610781077The pinch gesture handler in the old API will no longer be supported. Transitioning to the gestures API is recommended. Consult the upgrading guide for more details.
1079107810801080-### Force Touch
10791079+#### Force Touch
1081108010821081Force touch functionality from the legacy API will be deprecated. Migrating to the gestures API is advised. See the upgrading guide for further information.
1083108210841084-## NativeView
10831083+### NativeView
1085108410861085The `NativeView` component in the old API will be removed. Users should adopt the new gestures API and refer to the upgrading guide for assistance.
1087108610881088-## createNativeWrapper()
10871087+### createNativeWrapper()
1089108810901089The `createNativeWrapper()` function from the legacy API will no longer be supported. Transitioning to the gestures API is recommended. Consult the upgrading guide for more details.
10911091-```
1092109010931091## Testing with Jest
10941092···1343134113441342By setting `touchAction` to `"pan-y"`, you allow vertical panning, which helps maintain scroll functionality in your custom swipeable component.
1345134313461346-## Cross Handler Interactions
13441344+## Cross handler interactions
1347134513481346**Warning:** The old API will be removed in future versions of Gesture Handler. Please migrate to the gestures API instead. Refer to our upgrading guide for more information.
13491347···14291427);
14301428```
1431142914321432-## Fling Gesture
14301430+## Fling gesture
1433143114341432A discrete gesture activated by sufficiently long and fast movement. The gesture becomes ACTIVE when the movement meets these criteria, transitioning to END upon finger release. If the finger lifts before activation, recognition fails.
14351433···15371535|`numberOfPointers`|Number of pointers currently on the screen.|
15381536|`pointerType`|Type of pointer device, using `PointerType`: `TOUCH`, `STYLUS`, `MOUSE`, `KEY`, `OTHER`.|
1539153715401540-## Common Handler Properties
15381538+## Common handler properties
1541153915421540**Warning:** The old API will be removed in future versions of Gesture Handler. Please migrate to the gestures API instead. Refer to our upgrading guide for more information.
15431541···1617161516181616- **Description:** Represents the number of pointers (fingers) currently on the screen.
1619161716201620-## Hover Gesture
16181618+## Hover gesture
1621161916221620A continuous gesture designed to recognize hovering actions over a view. This can be triggered by moving a mouse or stylus above the view.
16231621···2042204020432041This example sets up a button that triggers an alert when held down for more than 800 milliseconds.
2044204220452045-## Custom Swipeable Components in ScrollView (Web)
20432043+## Custom swipeable components inside ScrollView (web)
2046204420472045When developing custom swipeable components within a `ScrollView` on the web, you might opt for more control over their behavior by creating your own version instead of using pre-built solutions like ReanimatedSwipeable. However, one common issue encountered is that scrolling functionality may not work as expected after implementing a custom swipeable component.
20482046···2067206520682066By setting `touchAction` to `"pan-y"`, you allow the browser to handle vertical panning, which can resolve issues with scrolling when using custom swipeable components inside a `ScrollView`.
2069206720702070-## Migrating Away from RNGHEnabledRootView
20682068+## Migrating off RNGHEnabledRootView
2071206920722070### Update `MainActivity.java`
20732071···2117211521182116**Note:** `GestureHandlerRootView` behaves like a standard `View`. To ensure it fills the screen, you must pass `{ flex: 1 }`, similar to how you would with a regular View. By default, it will take on the size of its nested content.
2119211721202120-## Rotation Gesture Handler
21182118+## RotationGestureHandler
2121211921222120> **Warning:**\
21232121> The old API will be deprecated in future versions of Gesture Handler. It is recommended to migrate to the gestures API. Refer to our upgrading guide for more details.
···2259225722602258This example shows a button that triggers an alert when flinged to the right or left.
2261225922622262-## Quick Start Guide
22602260+## Quick start
2263226122642262RNGH2 simplifies adding gestures to your application. To implement a gesture, wrap the target view with `GestureDetector`, define the desired gesture, and pass it to the detector.
22652263···2391238923922390Now, add the `Ball` component to a view in your app to see it in action!
2393239123942394-## Native Gesture
23922392+## Native gesture
2395239323962394A gesture that integrates with other touch handling components within RNGH's gesture system. This integration facilitates interactions between gestures and native components, allowing them to establish relationships with other gestures.
23972395···2731272927322730**Note**: For a detailed example, refer to the Gesture Handler Example App.
2733273127342734-## Manual Gesture
27322732+## Manual gesture
2735273327362734A manual gesture lacks specific activation criteria and event data. Its state must be managed manually using a state manager, ensuring it doesn't fail when all pointers are lifted from the screen.
27372735···28732871- `KEY`: Keyboard
28742872- `OTHER`: Unknown device type
2875287328762876-## Migrating from `RNGestureHandlerEnabledRootView` (Android Only)
28742874+## Make sure to migrate off the \`RNGestureHandlerEnabledRootView\` (Android only)
2877287528782876The `RNGestureHandlerEnabledRootView`, required in Gesture Handler 1 for overriding `createRootView`, was deprecated in version 2.0 and removed by version 2.4 due to its association with difficult-to-debug crashes. If you're still using it, refer to the guide on migrating off RNGHEnabledRootView.
28792877···2986298429872985For relations between gestures on the same view, use the Gesture Composition API. For different views or old gesture handlers, replace `simultaneousHandlers` with `simultaneousWithExternalGesture`, and `waitFor` with `requireExternalGestureToFail`. Use `.withRef(refObject)` to pass a ref object to an old handler.
2988298629892989-## Composed Gestures
29872987+## Composed gestures
2990298829912989Composed gestures such as `Race`, `Simultaneous`, and `Exclusive` offer a straightforward method for establishing relationships between different gestures. For further information, refer to the section on Gesture Composition.
29922990···3012301030133011This example demonstrates how to use the `Race` method to compose two gestures: a pan gesture and a long press gesture. The composed gesture is then used within a `GestureDetector` component, which wraps an `Animated.View`.
3014301230153015-## Common Handler Properties
30133013+## Common handler properties
3016301430173015**Warning:** The old API will be removed in future versions of Gesture Handler. Please migrate to the gestures API instead. Refer to our upgrading guide for more information.
30183016···3168316631693167The `GestureStateManager` allows manual control over gesture states. Note that react-native-reanimated is required for its use, as it enables synchronous execution of methods within worklets.
3170316831713171-## Touch Events
31693169+## Touch events
3172317031733171### Touch Event Attributes
31743172···3194319231953193- **absoluteY**: The Y coordinate of the current position of the touch relative to the window, expressed in point units. Recommended for use when the original view can be transformed due to a gesture.
3196319431973197-## Gesture State Manager
31953195+## Gesture state manager
3198319631993197The `GestureStateManager` provides manual control over gesture states, requiring `react-native-reanimated` for synchronous execution of methods within worklets.
32003198···32203218- **Purpose**: Transition the gesture to the `FAILED` state.
32213219- **Effectiveness**: Ineffective if the handler has already finished.
3222322032233223-## Touch Events
32213221+## Touch events
3224322232253223### Touch Event Attributes
32263224···3246324432473245- **absoluteY**: The Y coordinate of the current position of the touch relative to the window, expressed in point units. Recommended for use when the original view can be transformed due to a gesture.
3248324632493249-## Gesture State Manager
32473247+## Gesture state manager
3250324832513249The `GestureStateManager` provides manual control over gesture states, requiring `react-native-reanimated` for synchronous execution of methods within worklets.
32523250···36003598}
36013599```
3602360036033603-## Gesture Composition & Interactions
36013601+## Gesture composition & interactions
3604360236053603In RNGH2, composing gestures has been simplified compared to previous versions. There is no longer a need to create a reference for each gesture that depends on another one. Instead, you can utilize the Race, Simultaneous, and Exclusive methods provided by the Gesture object.
36063604···3614361236153613These methods facilitate more intuitive and flexible gesture interactions within your application.
3616361436173617-## Manual Gestures
36153615+## Manual gestures
3618361636193617RNGH2 introduces manual gestures and touch events, allowing for custom gesture tracking. This guide demonstrates creating a simple gesture that tracks all pointers on the screen.
36203618···3787378537883786Manual gestures offer powerful customization, enabling complex interactions. Additionally, existing gestures can be modified with `manualActivation` to control activation behavior, such as implementing drag after a long press by setting `manualActivation` on a `PanGesture`.
3789378737903790-## Pressable Component
37883788+## Pressable
3791378937923790### Overview
37933791···38703868});
38713869```
3872387038733873-## Gesture Composition & Interactions
38713871+## Gesture composition & interactions
3874387238753873Composing gestures in RNGH2 is straightforward. You don't need to create a ref for each gesture that depends on another one. Instead, use `Race`, `Simultaneous`, and `Exclusive` methods provided by the `Gesture` object.
38763874···4428442644294427We are grateful for our sponsors who enable the development of this library and contribute to enhancing the React Native ecosystem. Special thanks to all our supporters!
4430442844314431-## Troubleshooting Guide
44294429+## Troubleshooting
4432443044334431### Seeking Help with Issues
44344432···4510450845114509This ensures proper workletization for asynchronous operations within gestures.
4512451045134513-## Tap Gesture
45114511+## Tap gesture
4514451245154513A tap gesture recognizes one or multiple taps. It detects brief touches on the screen by fingers, which must remain relatively stationary from their initial positions. You can configure tap gestures to recognize single, double, or triple taps based on specific requirements such as `minPointers`, `numberOfTaps`, `maxDist`, `maxDuration`, and `maxDelayMs`.
45164514···48114809});
48124810```
4813481148144814-## Swipeable Component
48124812+## Swipeable
4815481348164814**Caution:** This component facilitates the implementation of swipeable rows or similar interactions. It renders its children within a panable container, allowing for horizontal swiping left and right. Depending on whether the user swipes left or right, one of two "action" containers can be displayed, rendered by `renderLeftActions` or `renderRightActions` props.
48174815···4988498649894987For a comparison of both touchable implementations, refer to our touchables example.
4990498849914991-```markdown
49924992-# Handler State
49894989+## Handler State
4993499049944991Gesture handlers are conceptualized as "state machines" according to the description provided in "About Gesture Handlers". This means they operate through a series of states, transitioning between them based on specific inputs or events.
49954995-```
4996499249974997-## How It Works
49934993+## How does it work?
4998499449994995### Units
50004996
+3655-3817
out/llms-full-react-native-reanimated.txt
···11-# React Native Reanimated
11+# React NativeReanimated
2233### Create Smooth Animations with an Excellent Developer Experience
44···221221|-|-|-|
222222|✅|✅|✅|
223223224224-## useAnimatedScrollHandler
224224+## Shared Element Transitions
225225226226-The `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.
226226+> **Caution:**\
227227+> Shared Element Transition is an experimental feature and not recommended for production use yet. Feedback is welcomed to enhance its implementation.
228228+229229+Shared Element Transition enables a smooth transformation of a component from one screen to another.
227230228231### Reference
229232230233```typescript
231231-import { useAnimatedScrollHandler } from 'react-native-reanimated';
234234+import Animated from 'react-native-reanimated';
232235233233-function App() {
234234- const offsetY = useSharedValue(0);
236236+const Stack = createNativeStackNavigator();
235237236236- const scrollHandler = useAnimatedScrollHandler((event) => {
237237- offsetY.value = event.contentOffset.y;
238238- });
239239-240240- // ...
241241-242242- return <Animated.ScrollView onScroll={scrollHandler} />;
238238+function One({ navigation }) {
239239+ return (
240240+ <>
241241+ <Animated.View sharedTransitionTag="sharedTag" />
242242+ <Button title="Two" onPress={() => navigation.navigate('Two')} />
243243+ </>
244244+ );
243245}
244244-```
245245-246246-#### Arguments
247246248248-##### `handlers`
249249-250250-An object containing custom keys that correspond to native event names. Available keys include:
251251-252252-- `onScroll`
253253-- `onBeginDrag`
254254-- `onEndDrag`
255255-- `onMomentumBegin`
256256-- `onMomentumEnd`
257257-258258-Each key should map to an individual worklet function. These functions are triggered when the associated events occur on a connected Scrollable component.
259259-260260-The event worklets receive two parameters:
261261-262262-- `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.
263263-264264-- `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.
265265-266266-##### `dependencies` (Optional)
267267-268268-An optional array of dependencies, relevant only when using Reanimated without the Babel plugin on the Web.
269269-270270-#### Returns
271271-272272-The 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`.
273273-274274-### Example
275275-276276-### Remarks
277277-278278-- The returned handler can be passed to multiple components. It will invoke for the specified events whenever any component dispatches them.
279279-- 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.
280280-- Only the `onScroll` event is supported on Web.
281281-282282-### Platform Compatibility
283283-284284-|Android|iOS|Web|
285285-|-|-|-|
286286-|✅|✅|✅|
287287-288288-## useEvent Hook Overview
289289-290290-The `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`.
291291-292292-### Reference Usage
293293-294294-```typescript
295295-import { useEvent } from 'react-native-reanimated';
296296-297297-function useAnimatedPagerScrollHandler(handlers, dependencies) {
298298- const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
299299-300300- return useEvent(
301301- (event) => {
302302- 'worklet';
303303- const { onPageScroll } = handlers;
304304-305305- if (onPageScroll && event.eventName.endsWith('onPageScroll')) {
306306- onPageScroll(event, context);
307307- }
308308- },
309309- ['onPageScroll'],
310310- doDependenciesDiffer
247247+function Two({ navigation }) {
248248+ return (
249249+ <>
250250+ <Animated.View sharedTransitionTag="sharedTag" />
251251+ <Button title="One" onPress={() => navigation.navigate('One')} />
252252+ </>
311253 );
312254}
313255314314-return <Animated.View onScroll={useAnimatedPagerScrollHandler} />;
256256+export default function SharedElementExample() {
257257+ return (
258258+ <NavigationContainer>
259259+ <Stack.Navigator screenOptions={{ headerShown: true }}>
260260+ <Stack.Screen name="One" component={One} />
261261+ <Stack.Screen name="Two" component={Two} />
262262+ </Stack.Navigator>
263263+ </NavigationContainer>
264264+ );
265265+}
315266```
316267317317-#### Arguments
318318-319319-- **`handler`**: A function that receives an event object containing the native payload. This can be utilized within custom handler hooks' worklets.
320320-321321- - `event`: The event object, whose payload varies based on the event type.
322322-323323-- **`eventNames` (Optional)**: An array specifying which event names should trigger the handler.
268268+### Overview
324269325325-- **`rebuild` (Optional)**: A boolean indicating if the handler needs to be rebuilt.
270270+When 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.
326271327327-#### Returns
272272+Without custom animations, properties like `width`, `height`, `originX`, `originY`, and `transformMatrix` animate by default over 500ms using `withTiming`.
328273329329-The 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.
274274+### Implementation
330275331331-### Example
276276+To 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.
332277333333-For simpler implementations, consider using `useScrollViewOffset`.
334334-335335-### Remarks
336336-337337-- Note that not all scroll events are supported on the web; only `onScroll` is consistently available across browsers.
338338-339339-### Platform Compatibility
340340-341341-|Android|iOS|Web|
342342-|-|-|-|
343343-|✅|✅|✅|
344344-345345-This overview provides a concise guide to using the `useEvent` hook effectively within React Native Reanimated projects.
346346-347347-## useHandler Hook in React Native Reanimated
348348-349349-The `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`.
350350-351351-### Reference
278278+**Screen A**
352279353280```typescript
354354-import { useEvent, useHandler } from "react-native-reanimated"
355355-356356-function useAnimatedPagerScrollHandler(
357357- handlers: Record<string, (event: any, context: object) => void>,
358358- dependencies?: any[]
359359-) {
360360- const { context, doDependenciesDiffer, useWeb } = useHandler(
361361- handlers,
362362- dependencies
363363- )
364364-365365- return useEvent(
366366- (event: any) => {
367367- "worklet"
368368- const { onPageScroll } = handlers
369369-370370- if (onPageScroll && event.eventName.endsWith("onPageScroll")) {
371371- onPageScroll(event, context)
372372- }
373373- },
374374- ["onPageScroll"],
375375- doDependenciesDiffer
376376- )
377377-}
281281+<View
282282+ sharedTransitionTag="sharedTag"
283283+ style={{ width: 150, height: 150, backgroundColor: 'green' }}
284284+/>
378285```
379286380380-#### Arguments
287287+**Screen B**
381288382382-##### `handlers`
289289+```typescript
290290+<View
291291+ sharedTransitionTag="sharedTag"
292292+ style={{ width: 100, height: 100, backgroundColor: 'green' }}
293293+/>
294294+```
383295384384-An 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.
296296+### Custom Animation
385297386386-Each event worklet receives:
298298+Custom animations can be created using `SharedTransition.custom` for regular animations or `SharedTransition.progressAnimation` for progress-based ones.
387299388388-- `event`: An event object whose payload varies based on the event type.
389389-- `context`: A plain JavaScript object for storing state, persisting between events. This allows communication among multiple event handlers provided as an object of worklets.
300300+```typescript
301301+import { SharedTransition } from "react-native-reanimated"
390302391391-##### `dependencies` (Optional)
392392-393393-An optional array of dependencies. This is relevant when using Reanimated without its Babel plugin in a web environment.
394394-395395-#### Returns
396396-397397-The hook returns:
398398-399399-- A context reused by event handlers.
400400-- An indicator to determine if worklets should be rebuilt.
401401-- A boolean, `useWeb`, to check for the web environment if different implementations are needed.
402402-403403-### Example
303303+const transition = SharedTransition.custom((values) => {
304304+ "worklet"
305305+ return {
306306+ height: withSpring(values.targetHeight),
307307+ width: withSpring(values.targetWidth),
308308+ }
309309+})
310310+ .progressAnimation((values, progress) => {
311311+ "worklet"
312312+ const getValue = (
313313+ progress: number,
314314+ target: number,
315315+ current: number
316316+ ): number => {
317317+ return progress * (target - current) + current
318318+ }
319319+ return {
320320+ width: getValue(progress, values.targetWidth, values.currentWidth),
321321+ height: getValue(progress, values.targetHeight, values.currentHeight),
322322+ }
323323+ })
324324+ .defaultTransitionType(SharedTransitionType.ANIMATION)
325325+```
404326405405-For simpler implementations, consider using `useScrollViewOffset`.
327327+By 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.
406328407407-### Platform Compatibility
408408-409409-|Android|iOS|Web|
410410-|-|-|-|
411411-|✅|✅|✅|
412412-413413-This documentation provides a comprehensive overview of how to utilize the `useHandler` hook within React Native Reanimated for creating custom event handlers.
414414-415415-## Keyframe Animations
416416-417417-Keyframes provide a schema for defining animations, offering more flexibility than standard Entering and Exiting presets. They allow you to create complex animations with ease.
418418-419419-### Reference
329329+To 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.
420330421331```typescript
422422-import { Keyframe } from 'react-native-reanimated';
423423-424424-const keyframe = new Keyframe({
425425- 0: {
426426- transform: [{ rotate: '0deg' }],
427427- },
428428- 45: {
429429- transform: [{ rotate: '100deg' }],
430430- easing: Easing.exp,
431431- },
432432- 100: {
433433- transform: [{ rotate: '45deg' }],
434434- },
435435-});
436436-437437-function App() {
438438- return <Animated.View entering={keyframe} />;
439439-}
332332+<View
333333+ sharedTransitionTag="reanimatedTransition"
334334+ sharedTransitionStyle={transition}
335335+ style={{ backgroundColor: 'blue', width: 200, height: 100 }}
336336+/>
440337```
441338442442-#### Arguments
443443-444444-##### `definitions`
445445-446446-An 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.
447447-448448-Key values include:
339339+### Example
449340450450-- `0` or `from`: Represents the initial state.
451451-- Intermediate points (e.g., `45`): Represent intermediate states.
452452-- `100` or `to`: Represents the final state.
341341+Your browser does not support the video tag.
453342454454-The key `0` (or `from`) should define the style at the start of the animation, while `100` (or `to`) defines it at the end.
343343+Your browser does not support the video tag.
455344456456-### Modifiers
345345+Expand the full code:
457346458347```typescript
459459-keyframe
460460- .duration(1000)
461461- .delay(500)
462462- .reduceMotion(ReduceMotion.Never)
463463- .withCallback((finished) => {
464464- console.log(`finished without interruptions: ${finished}`)
465465- })
348348+<Pressable onPress={() => goToDetails('countryside')}>
349349+ <Animated.View
350350+ sharedTransitionTag={'countryside'}
351351+ style={[
352352+ styles.imageOne,
353353+ { backgroundColor: gallery.countryside.color },
354354+ ]}
355355+ />
356356+</Pressable>
357357+<View style={styles.row}>
358358+ <Pressable onPress={() => goToDetails('florence')}>
359359+ <Animated.View
360360+ sharedTransitionTag={'florence'}
361361+ style={[
362362+ { width: width / 2 - 35 },
363363+ styles.imageTwo,
364364+ { backgroundColor: gallery.florence.color },
365365+ ]}
366366+ />
367367+ </Pressable>
368368+ <Pressable onPress={() => goToDetails('dawn')}>
369369+ <Animated.View
370370+ sharedTransitionTag={'dawn'}
371371+ style={[
372372+ { width: width / 2 - 35 },
373373+ styles.imageThree,
374374+ { backgroundColor: gallery.dawn.color },
375375+ ]}
376376+ />
377377+ </Pressable>
378378+</View>
466379```
467380468468-- `.duration(durationMs: number)` sets the animation length in milliseconds, defaulting to `500`.
469469-- `.delay(durationMs: number)` specifies a delay before starting the animation, defaulting to `0`.
470470-- `.reduceMotion(reduceMotion: ReduceMotion)` adjusts the animation based on the device's reduced motion setting.
471471-- `.withCallback(callback: (finished: boolean) => void)` triggers after the animation ends, indicating if it finished without interruptions.
472472-473381### Remarks
474382475475-- Providing keyframe `0` or `from` is mandatory as it defines the initial state of the object to be animated.
476476-- Ensure all style properties intended for animation have an initial value in other keyframes.
477477-- Easing should only be applied to subsequent keyframes, not to keyframe `0`.
478478-- Avoid using both `0` and `from`, or `100` and `to`, as it causes parsing conflicts.
479479-- When animating transform styles, maintain the order of properties consistently across all keyframes.
383383+- Only the native stack is supported.
384384+- Animatable properties include `width`, `height`, `originX`, `originY`, and `transformMatrix`.
385385+- Layout for shared view children isn't computed during transitions.
386386+- Currently supports only the old React Native architecture (Paper).
387387+- Future support for the new React Native architecture (Fabric) is planned.
480388481389### Platform Compatibility
482390483391|Android|iOS|Web|
484392|-|-|-|
485485-|✅|✅|✅|
393393+|✅|✅|❌|
486394487395## Troubleshooting
488396···737645738646For more information, refer to Reanimated's documentation on worklets.
739647740740-## Shared Element Transitions
741741-742742-> **Caution:**\
743743-> Shared Element Transition is an experimental feature and not recommended for production use yet. Feedback is welcomed to enhance its implementation.
744744-745745-Shared Element Transition enables a smooth transformation of a component from one screen to another.
746746-747747-### Reference
748748-749749-```typescript
750750-import Animated from 'react-native-reanimated';
751751-752752-const Stack = createNativeStackNavigator();
753753-754754-function One({ navigation }) {
755755- return (
756756- <>
757757- <Animated.View sharedTransitionTag="sharedTag" />
758758- <Button title="Two" onPress={() => navigation.navigate('Two')} />
759759- </>
760760- );
761761-}
762762-763763-function Two({ navigation }) {
764764- return (
765765- <>
766766- <Animated.View sharedTransitionTag="sharedTag" />
767767- <Button title="One" onPress={() => navigation.navigate('One')} />
768768- </>
769769- );
770770-}
771771-772772-export default function SharedElementExample() {
773773- return (
774774- <NavigationContainer>
775775- <Stack.Navigator screenOptions={{ headerShown: true }}>
776776- <Stack.Screen name="One" component={One} />
777777- <Stack.Screen name="Two" component={Two} />
778778- </Stack.Navigator>
779779- </NavigationContainer>
780780- );
781781-}
782782-```
783783-784784-### Overview
785785-786786-When 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.
787787-788788-Without custom animations, properties like `width`, `height`, `originX`, `originY`, and `transformMatrix` animate by default over 500ms using `withTiming`.
789789-790790-### Implementation
791791-792792-To 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.
793793-794794-**Screen A**
795795-796796-```typescript
797797-<View
798798- sharedTransitionTag="sharedTag"
799799- style={{ width: 150, height: 150, backgroundColor: 'green' }}
800800-/>
801801-```
802802-803803-**Screen B**
804804-805805-```typescript
806806-<View
807807- sharedTransitionTag="sharedTag"
808808- style={{ width: 100, height: 100, backgroundColor: 'green' }}
809809-/>
810810-```
811811-812812-### Custom Animation
813813-814814-Custom animations can be created using `SharedTransition.custom` for regular animations or `SharedTransition.progressAnimation` for progress-based ones.
815815-816816-```typescript
817817-import { SharedTransition } from "react-native-reanimated"
818818-819819-const transition = SharedTransition.custom((values) => {
820820- "worklet"
821821- return {
822822- height: withSpring(values.targetHeight),
823823- width: withSpring(values.targetWidth),
824824- }
825825-})
826826- .progressAnimation((values, progress) => {
827827- "worklet"
828828- const getValue = (
829829- progress: number,
830830- target: number,
831831- current: number
832832- ): number => {
833833- return progress * (target - current) + current
834834- }
835835- return {
836836- width: getValue(progress, values.targetWidth, values.currentWidth),
837837- height: getValue(progress, values.targetHeight, values.currentHeight),
838838- }
839839- })
840840- .defaultTransitionType(SharedTransitionType.ANIMATION)
841841-```
842842-843843-By 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.
844844-845845-To 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.
846846-847847-```typescript
848848-<View
849849- sharedTransitionTag="reanimatedTransition"
850850- sharedTransitionStyle={transition}
851851- style={{ backgroundColor: 'blue', width: 200, height: 100 }}
852852-/>
853853-```
854854-855855-### Example
856856-857857-Your browser does not support the video tag.
858858-859859-Your browser does not support the video tag.
860860-861861-Expand the full code:
862862-863863-```typescript
864864-<Pressable onPress={() => goToDetails('countryside')}>
865865- <Animated.View
866866- sharedTransitionTag={'countryside'}
867867- style={[
868868- styles.imageOne,
869869- { backgroundColor: gallery.countryside.color },
870870- ]}
871871- />
872872-</Pressable>
873873-<View style={styles.row}>
874874- <Pressable onPress={() => goToDetails('florence')}>
875875- <Animated.View
876876- sharedTransitionTag={'florence'}
877877- style={[
878878- { width: width / 2 - 35 },
879879- styles.imageTwo,
880880- { backgroundColor: gallery.florence.color },
881881- ]}
882882- />
883883- </Pressable>
884884- <Pressable onPress={() => goToDetails('dawn')}>
885885- <Animated.View
886886- sharedTransitionTag={'dawn'}
887887- style={[
888888- { width: width / 2 - 35 },
889889- styles.imageThree,
890890- { backgroundColor: gallery.dawn.color },
891891- ]}
892892- />
893893- </Pressable>
894894-</View>
895895-```
896896-897897-### Remarks
898898-899899-- Only the native stack is supported.
900900-- Animatable properties include `width`, `height`, `originX`, `originY`, and `transformMatrix`.
901901-- Layout for shared view children isn't computed during transitions.
902902-- Currently supports only the old React Native architecture (Paper).
903903-- Future support for the new React Native architecture (Fabric) is planned.
904904-905905-### Platform Compatibility
906906-907907-|Android|iOS|Web|
908908-|-|-|-|
909909-|✅|✅|❌|
910910-911648## useAnimatedScrollHandler
912649913650The `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.
···972709|-|-|-|
973710|✅|✅|✅|
974711975975-## scrollTo Function in React Native Reanimated
712712+## useAnimatedScrollHandler
976713977977-The `scrollTo` function allows you to synchronously scroll a component to a specified X or Y offset.
714714+The `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.
978715979716### Reference
980717981718```typescript
982982-import { scrollTo } from 'react-native-reanimated';
719719+import { useAnimatedScrollHandler } from 'react-native-reanimated';
983720984721function App() {
985985- const animatedRef = useAnimatedRef();
986986- const scrollY = useSharedValue(0);
722722+ const offsetY = useSharedValue(0);
987723988988- useDerivedValue(() => {
989989- scrollTo(animatedRef, 0, scrollY.value, true);
724724+ const scrollHandler = useAnimatedScrollHandler((event) => {
725725+ offsetY.value = event.contentOffset.y;
990726 });
991727992992- return (
993993- <Animated.ScrollView ref={animatedRef}>{/* ... */}</Animated.ScrollView>
994994- );
728728+ // ...
729729+730730+ return <Animated.ScrollView onScroll={scrollHandler} />;
995731}
996732```
997733998734#### Arguments
99973510001000-- **`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.
10011001-10021002-- **`x`**: The pixel value for horizontal scrolling on the X axis.
10031003-10041004-- **`y`**: The pixel value for vertical scrolling on the Y axis.
10051005-10061006-- **`animated`**: A boolean indicating if the scroll should be smooth (`true`) or instant (`false`).
10071007-10081008-#### Returns
10091009-10101010-The `scrollTo` function returns `undefined`.
10111011-10121012-### Remarks
10131013-10141014-- The `scrollTo` function must be invoked from the UI thread.
10151015-- It supports `Animated.FlatList`.
10161016-- Typically works with other ScrollView-like and FlatList-like components if they use a `ScrollView` internally and are animated.
10171017-- Scrollable components need to implement the `getScrollableNode` method (and `getNativeScrollRef` for New Architecture) to be compatible with `scrollTo`.
10181018-10191019-### Platform Compatibility
10201020-10211021-|Android|iOS|Web|
10221022-|-|-|-|
10231023-|✅|✅|✅|
10241024-10251025-## getRelativeCoords Functionality
10261026-10271027-The `getRelativeCoords` function is used to determine the screen location relative to a specified view.
10281028-10291029-### Reference Code
10301030-10311031-```typescript
10321032-import { getRelativeCoords } from 'react-native-reanimated';
10331033-10341034-const Comp = () => {
10351035- const animatedRef = useAnimatedRef();
10361036-10371037- const gestureHandler = useAnimatedGestureHandler({
10381038- onEnd: (event) => {
10391039- const coords = getRelativeCoords(
10401040- animatedRef,
10411041- event.absoluteX,
10421042- event.absoluteY
10431043- );
10441044- },
10451045- });
10461046-10471047- return (
10481048- <View ref={animatedRef}>
10491049- <PanGestureHandler onGestureEvent={gestureHandler}>
10501050- <Animated.View style={[styles.box]} />
10511051- </PanGestureHandler>
10521052- </View>
10531053- );
10541054-};
10551055-```
10561056-10571057-### Arguments
10581058-10591059-- **`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.
736736+##### `handlers`
106073710611061-- **`absoluteX`**: A number representing the absolute x-coordinate.
738738+An object containing custom keys that correspond to native event names. Available keys include:
106273910631063-- **`absoluteY`**: A number representing the absolute y-coordinate.
10641064-10651065-### Returns
10661066-10671067-An object containing:
10681068-10691069-- `x`: The relative x-coordinate.
10701070-- `y`: The relative y-coordinate.
740740+- `onScroll`
741741+- `onBeginDrag`
742742+- `onEndDrag`
743743+- `onMomentumBegin`
744744+- `onMomentumEnd`
107174510721072-### Platform Compatibility
746746+Each key should map to an individual worklet function. These functions are triggered when the associated events occur on a connected Scrollable component.
107374710741074-|Android|iOS|Web|
10751075-|-|-|-|
10761076-|✅|✅|✅|
748748+The event worklets receive two parameters:
107774910781078-## useAnimatedGestureHandler
750750+- `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.
107975110801080-**Warning:**\
10811081-The `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.
10821082-10831083-This hook necessitates that `react-native-gesture-handler` be installed and configured within your project.
10841084-10851085-### Reference
10861086-10871087-```typescript
10881088-import { useAnimatedGestureHandler } from 'react-native-reanimated';
10891089-import { PanGestureHandler } from 'react-native-gesture-handler';
10901090-10911091-function App() {
10921092- const x = useSharedValue(0);
10931093-10941094- const gestureHandler = useAnimatedGestureHandler({
10951095- onStart: (_, ctx) => {
10961096- ctx.startX = x.value;
10971097- },
10981098- onActive: (event, ctx) => {
10991099- x.value = ctx.startX + event.translationX;
11001100- },
11011101- });
11021102-11031103- return (
11041104- <PanGestureHandler onGestureEvent={gestureHandler}>
11051105- <Animated.View />
11061106- </PanGestureHandler>
11071107- );
11081108-}
11091109-```
11101110-11111111-#### Arguments
11121112-11131113-##### `gestureHandlers`
11141114-11151115-The 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`.
11161116-11171117-Each 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:
11181118-11191119-- `event` \[object] - an event object containing the payload specific to the type of gesture handler (e.g., `PanGestureHandler`, `RotationGestureHandler`).
11201120-11211121-- `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.
752752+- `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.
11227531123754##### `dependencies` (Optional)
112475511251125-An optional array of dependencies is relevant only when using Reanimated without the Babel plugin on the Web.
756756+An optional array of dependencies, relevant only when using Reanimated without the Babel plugin on the Web.
11267571127758#### Returns
112875911291129-The `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.
760760+The 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`.
11307611131762### Example
113276311331133-### Platform Compatibility
11341134-11351135-|Android|iOS|Web|
11361136-|-|-|-|
11371137-|✅|✅|⚠️|
11381138-11391139-- On the Web, it is necessary to pass the returned handler object to both `onGestureEvent` and `onHandlerStateChange` parameters.
11401140-11411141-## useScrollViewOffset Hook
11421142-11431143-The `useScrollViewOffset` hook enables the creation of animations based on a `ScrollView`'s offset. It automatically determines whether the `ScrollView` is oriented horizontally or vertically.
11441144-11451145-### Reference
764764+### Remarks
114676511471147-```typescript
11481148-import { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
11491149-11501150-function App() {
11511151- const animatedRef = useAnimatedRef();
11521152- const scrollOffset = useScrollViewOffset(animatedRef);
11531153-11541154- return (
11551155- <Animated.ScrollView ref={animatedRef}>
11561156- {/* Content goes here */}
11571157- </Animated.ScrollView>
11581158- );
11591159-}
11601160-```
11611161-11621162-#### Arguments
11631163-11641164-##### `animatedRef`
11651165-11661166-An 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.
11671167-11681168-##### `initialRef` (Optional)
11691169-11701170-A shared value that can optionally be updated with the scroll offset. If not provided, a new shared value will be created internally by default.
11711171-11721172-#### Returns
11731173-11741174-The hook returns a shared value representing the current offset of the `ScrollView`.
11751175-11761176-### Example Usage
11771177-11781178-- The `animatedRef` argument can be dynamically changed, and the hook will continue to provide accurate values based on the connected `ScrollView`. For instance:
11791179-11801180- ```typescript
11811181- useScrollViewOffset(someState ? someScrollRefA : someScrollRefB)
11821182- ```
766766+- The returned handler can be passed to multiple components. It will invoke for the specified events whenever any component dispatches them.
767767+- 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.
768768+- Only the `onScroll` event is supported on Web.
11837691184770### Platform Compatibility
1185771···1187773|-|-|-|
1188774|✅|✅|✅|
118977511901190-```markdown
11911191-# Advanced APIs - Version 3.x
11921192-11931193-## measure
11941194-11951195-`measure` allows synchronous retrieval of a view's dimensions and position on the screen, executed on the UI thread.
11961196-11971197-## useAnimatedReaction
11981198-11991199-`useAnimatedReaction` enables response to changes in a shared value. It is particularly useful for comparing previous values stored in the shared value with their current counterparts.
12001200-12011201-## useFrameCallback
12021202-12031203-`useFrameCallback` facilitates running a function during each frame update.
12041204-1205776## useEvent
120677712071207-`useEvent` is a foundational hook that returns an event handler triggered by native events. This can be utilized to create custom event handler hooks, such as `useScrollViewOffset` or `useAnimatedScrollHandler`.
778778+The `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`.
120877912091209-## useHandler
12101210-12111211-`useHandler` is another fundamental hook providing a context object and a value indicating if the worklet requires rebuilding. It aids in creating custom event handler hooks like `useScrollViewOffset` or `useAnimatedScrollHandler`.
12121212-12131213-## useComposedEventHandler
12141214-12151215-This hook allows for the composition of `useEvent`-based event handlers (e.g., `useAnimatedScrollHandler` or custom ones) into a single, unified event handler.
12161216-12171217-## dispatchCommand
12181218-12191219-`dispatchCommand` enables execution of commands on a native component directly from the UI thread.
12201220-12211221-## setNativeProps
12221222-12231223-`setNativeProps` allows for imperative updates to component properties.
12241224-12251225-## makeMutable
12261226-12271227-The use of `makeMutable` is generally discouraged. It's advised to opt for the `useSharedValue` hook unless you are fully aware of its implications and consequences (refer to the Remarks section).
12281228-```
12291229-12301230-## Handling Gestures
12311231-12321232-This 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.
12331233-12341234-Ensure you've completed the Gesture Handler installation steps before proceeding.
12351235-12361236-### Handling Tap Gestures
12371237-12381238-We begin with tap gestures, which detect brief screen touches. These can be used for custom buttons or pressable elements.
12391239-12401240-In this example, a circle grows and changes color upon touch.
12411241-12421242-First, wrap your app in `GestureHandlerRootView` to ensure gesture functionality:
780780+### Reference Usage
12437811244782```typescript
12451245-import { GestureHandlerRootView } from 'react-native-gesture-handler';
12461246-12471247-function App() {
12481248- return (
12491249- <GestureHandlerRootView style={{ flex: 1 }}>
12501250- {/* rest of the app */}
12511251- </GestureHandlerRootView>
12521252- );
12531253-}
12541254-```
12551255-12561256-Define tap gestures using `Gesture.Tap()` and chain methods like `onBegin`, `onStart`, `onEnd`, or `onFinalize` to update shared values:
12571257-12581258-```typescript
12591259-export default function App() {
12601260- const pressed = useSharedValue<boolean>(false);
12611261-12621262- const tap = Gesture.Tap()
12631263- .onBegin(() => {
12641264- pressed.value = true;
12651265- })
12661266- .onFinalize(() => {
12671267- pressed.value = false;
12681268- });
12691269-```
783783+import { useEvent } from 'react-native-reanimated';
127078412711271-Access shared values safely as gesture callbacks are automatically workletized.
785785+function useAnimatedPagerScrollHandler(handlers, dependencies) {
786786+ const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
127278712731273-Define animation logic using `withTiming` in `useAnimatedStyle`:
788788+ return useEvent(
789789+ (event) => {
790790+ 'worklet';
791791+ const { onPageScroll } = handlers;
127479212751275-```typescript
12761276-const animatedStyles = useAnimatedStyle(() => ({
12771277- backgroundColor: pressed.value ? "#FFE04B" : "#B58DF1",
12781278- transform: [{ scale: withTiming(pressed.value ? 1.2 : 1) }],
12791279-}))
12801280-```
12811281-12821282-Pass the gesture to `GestureDetector` and apply `animatedStyles`:
12831283-12841284-```typescript
12851285- return (
12861286- <GestureHandlerRootView style={styles.container}>
12871287- <View style={styles.container}>
12881288- <GestureDetector gesture={tap}>
12891289- <Animated.View style={[styles.circle, animatedStyles]} />
12901290- </GestureDetector>
12911291- </View>
12921292- </GestureHandlerRootView>
793793+ if (onPageScroll && event.eventName.endsWith('onPageScroll')) {
794794+ onPageScroll(event, context);
795795+ }
796796+ },
797797+ ['onPageScroll'],
798798+ doDependenciesDiffer
1293799 );
1294800}
12951295-```
129680112971297-### Handling Pan Gestures
12981298-12991299-Enhance the circle by making it draggable and bouncing back to its starting position upon release. Retain color highlight and scale effects.
13001300-13011301-Switch from `Tap` to `Pan` gesture and add an `onChange` method:
13021302-13031303-```typescript
13041304-const offset = useSharedValue<number>(0);
13051305-13061306-const pan = Gesture.Pan()
13071307- .onBegin(() => {
13081308- pressed.value = true;
13091309- })
13101310- .onChange((event) => {
13111311- offset.value = event.translationX;
13121312- })
13131313- .onFinalize(() => {
13141314- offset.value = withSpring(0);
13151315- pressed.value = false;
13161316-```
13171317-13181318-Use `translationX` from the event data to move the circle. Reset `offset.value` in `onFinalize` using `withSpring`.
13191319-13201320-Adjust `useAnimatedStyle` for handling offset:
13211321-13221322-```typescript
13231323-const animatedStyles = useAnimatedStyle(() => ({
13241324- transform: [
13251325- { translateX: offset.value },
13261326- { scale: withTiming(pressed.value ? 1.2 : 1) },
13271327- ],
13281328- backgroundColor: pressed.value ? "#FFE04B" : "#b58df1",
13291329-}))
13301330-```
13311331-13321332-### Using `withDecay`
13331333-13341334-`withDecay` retains gesture velocity for decelerating animations.
13351335-13361336-Pass final velocity in `onFinalize` to `withDecay`:
13371337-13381338-```typescript
13391339-const pan = Gesture.Pan()
13401340- .onChange((event) => {
13411341- offset.value += event.changeX;
13421342- })
13431343- .onFinalize((event) => {
13441344- offset.value = withDecay({
13451345- velocity: event.velocityX,
13461346- rubberBandEffect: true,
13471347- clamp: [
13481348- -(width.value / 2) + SIZE / 2 + BOUNDARY_OFFSET,
13491349- width.value / 2 - SIZE / 2 - BOUNDARY_OFFSET,
13501350-```
13511351-13521352-Ensure the square stays within screen bounds.
13531353-13541354-Explore `withDecay` API for more configuration options.
13551355-13561356-### Summary
13571357-13581358-This section covered gesture handling with Reanimated and Gesture Handler, focusing on `Tap`, `Pan`, and `withDecay`. Key points include:
13591359-13601360-- Integration of Reanimated with React Native Gesture Handler.
13611361-- Creation of gestures like `Gesture.Pan()` or `Gesture.Tap()`.
13621362-- Accessing shared values in gesture callbacks without extra boilerplate.
13631363-- Using `withDecay` for decelerating animations based on gesture velocity.
13641364-13651365-### What's Next?
13661366-13671367-Explore 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.
13681368-13691369-## withRepeat
13701370-13711371-`withRepeat` is an animation modifier that allows you to repeat a specified animation a certain number of times or indefinitely.
13721372-13731373-### Reference
13741374-13751375-```typescript
13761376-import { withRepeat } from "react-native-reanimated"
13771377-13781378-function App() {
13791379- sv.value = withRepeat(withSpring(0), 5)
13801380- // ...
13811381-}
802802+return <Animated.View onScroll={useAnimatedPagerScrollHandler} />;
1382803```
13838041384805#### Arguments
138580613861386-##### `animation`
807807+- **`handler`**: A function that receives an event object containing the native payload. This can be utilized within custom handler hooks' worklets.
138780813881388-The animation object you wish to repeat.
809809+ - `event`: The event object, whose payload varies based on the event type.
138981013901390-##### `numberOfReps` (Optional)
811811+- **`eventNames` (Optional)**: An array specifying which event names should trigger the handler.
139181213921392-Specifies how many times the animation should be repeated. The default is `2`.
813813+- **`rebuild` (Optional)**: A boolean indicating if the handler needs to be rebuilt.
139381413941394-A 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.
815815+#### Returns
139581613961396-##### `reverse` (Optional)
817817+The 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.
139781813981398-Determines whether the animation should alternate directions with each repetition. The default setting is `false`.
13991399-14001400-This feature only supports direct animation functions like `withSpring` and does not work with other animation modifiers such as `withSequence`.
14011401-14021402-##### `callback` (Optional)
14031403-14041404-A function that executes upon the completion of the animation. If the animation is canceled, the callback receives `false`; otherwise, it receives `true`.
14051405-14061406-##### `reduceMotion` (Optional)
14071407-14081408-Controls how the animation responds to the device's reduced motion accessibility setting.
14091409-14101410-#### Returns
819819+### Example
141182014121412-The `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`.
821821+For simpler implementations, consider using `useScrollViewOffset`.
14138221414823### Remarks
141582414161416-- The callback provided in the fourth argument is automatically workletized and executed on the UI thread.
825825+- Note that not all scroll events are supported on the web; only `onScroll` is consistently available across browsers.
14178261418827### Platform Compatibility
1419828···1421830|-|-|-|
1422831|✅|✅|✅|
142383214241424-## Measure Functionality in React Native Reanimated
833833+This overview provides a concise guide to using the `useEvent` hook effectively within React Native Reanimated projects.
834834+835835+## useHandler
142583614261426-The `measure` function allows you to synchronously obtain the dimensions and position of a view on the screen, executed on the UI thread.
837837+The `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`.
14278381428839### Reference
14298401430841```typescript
14311431-import { measure } from 'react-native-reanimated';
842842+import { useEvent, useHandler } from "react-native-reanimated"
143284314331433-function App() {
14341434- const animatedRef = useAnimatedRef();
844844+function useAnimatedPagerScrollHandler(
845845+ handlers: Record<string, (event: any, context: object) => void>,
846846+ dependencies?: any[]
847847+) {
848848+ const { context, doDependenciesDiffer, useWeb } = useHandler(
849849+ handlers,
850850+ dependencies
851851+ )
143585214361436- const handlePress = () => {
14371437- runOnUI(() => {
14381438- const measurement = measure(animatedRef);
14391439- if (measurement === null) {
14401440- return;
14411441- }
14421442- // Additional logic can be added here
14431443- })();
14441444- };
14451445-14461446- return <Animated.View ref={animatedRef} />;
14471447-}
14481448-```
14491449-14501450-#### Arguments
14511451-14521452-- **`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.
14531453-14541454-#### Returns
14551455-14561456-The `measure` function returns an object containing:
14571457-14581458-|Field|Description|
14591459-|-|-|
14601460-|`x`|A number representing the X coordinate relative to the parent component.|
14611461-|`y`|A number representing the Y coordinate relative to the parent component.|
14621462-|`width`|A number representing the width of the component.|
14631463-|`height`|A number representing the height of the component.|
14641464-|`pageX`|A number representing the X coordinate relative to the screen.|
14651465-|`pageY`|A number representing the Y coordinate relative to the screen.|
14661466-14671467-Alternatively, it returns `null` if the measurement could not be performed.
853853+ return useEvent(
854854+ (event: any) => {
855855+ "worklet"
856856+ const { onPageScroll } = handlers
146885714691469-### Remarks
14701470-14711471-- **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.
14721472-14731473-- **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:
14741474-14751475- ```typescript
14761476- function App() {
14771477- const animatedStyles = useAnimatedStyle(() => {
14781478- if (_WORKLET) {
14791479- // Safely use measure here
14801480- const measurement = measure(animatedRef)
14811481- }
14821482- })
14831483- }
14841484- ```
14851485-14861486-- **Consecutive Runs**: Subsequent executions of `useAnimatedStyle` occur on the UI thread.
14871487-14881488-- **Alternative for Static Dimensions**: If only static dimensions are needed and measurements aren't used during animations, consider using the `onLayout` property instead.
14891489-14901490-- **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:
14911491-14921492- ```typescript
14931493- const animatedRef = useAnimatedRef()
14941494-14951495- const handlePress = () => {
14961496- runOnUI(() => {
14971497- const measurement = measure(animatedRef)
14981498-14991499- if (measurement === null) {
15001500- return
15011501- }
15021502- // Additional logic can be added here
15031503- })()
15041504- }
15051505- ```
15061506-15071507-- **Rendered Components Only**: `measure` is applicable only to rendered components. For example, measuring off-screen items in a `FlatList` will yield `null`.
15081508-15091509-- **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.
15101510-15111511-### Platform Compatibility
15121512-15131513-|Android|iOS|Web|
15141514-|-|-|-|
15151515-|✅|✅|✅|
15161516-15171517-## useAnimatedReaction
15181518-15191519-The `useAnimatedReaction` hook enables responses to changes in shared values, particularly useful when comparing previous and current values stored within a shared value.
15201520-15211521-### Reference
15221522-15231523-```typescript
15241524-import { useAnimatedReaction } from "react-native-reanimated"
15251525-15261526-function App() {
15271527- useAnimatedReaction(
15281528- () => sv.value,
15291529- (currentValue, previousValue) => {
15301530- if (currentValue !== previousValue) {
15311531- // perform an action ✨
858858+ if (onPageScroll && event.eventName.endsWith("onPageScroll")) {
859859+ onPageScroll(event, context)
1532860 }
15331533- }
861861+ },
862862+ ["onPageScroll"],
863863+ doDependenciesDiffer
1534864 )
15351535-15361536- // ...
1537865}
1538866```
15398671540868#### Arguments
154186915421542-##### `prepare`
870870+##### `handlers`
154387115441544-A function returning the value to which you want to react. This returned value serves as the first parameter for the `react` argument.
872872+An 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.
154587315461546-```typescript
15471547-function App() {
15481548- useAnimatedReaction(
15491549- () => Math.floor(sv.value),
15501550- (currentValue, previousValue) => {
15511551- // ...
15521552- }
15531553- )
15541554-}
15551555-```
874874+Each event worklet receives:
155687515571557-##### `react`
15581558-15591559-A 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`.
15601560-15611561-```typescript
15621562-function App() {
15631563- useAnimatedReaction(
15641564- () => Math.floor(sv.value),
15651565- (currentValue, previousValue) => {
15661566- // ...
15671567- }
15681568- )
15691569-}
15701570-```
876876+- `event`: An event object whose payload varies based on the event type.
877877+- `context`: A plain JavaScript object for storing state, persisting between events. This allows communication among multiple event handlers provided as an object of worklets.
15718781572879##### `dependencies` (Optional)
157388015741574-An optional array of dependencies. This is only relevant when using Reanimated without the Babel plugin on the Web.
881881+An optional array of dependencies. This is relevant when using Reanimated without its Babel plugin in a web environment.
15758821576883#### Returns
157788415781578-The `useAnimatedReaction` hook returns `undefined`.
885885+The hook returns:
157988615801580-### Example
887887+- A context reused by event handlers.
888888+- An indicator to determine if worklets should be rebuilt.
889889+- A boolean, `useWeb`, to check for the web environment if different implementations are needed.
158189015821582-### Remarks
891891+### Example
158389215841584-- Avoid mutating the same shared value in the `react` function that was used in the `prepare` function to prevent infinite loops.
15851585-15861586-```typescript
15871587-function App() {
15881588- useAnimatedReaction(
15891589- () => width.value,
15901590- (currentValue) => {
15911591- // 🚨 An infinite loop!
15921592- width.value += currentValue
15931593- }
15941594- )
15951595-}
15961596-```
15971597-15981598-- Callbacks for both `prepare` and `react` are automatically workletized, running on the UI thread.
15991599-16001600-- While you can use `useAnimatedReaction` to react to any stateful React value, it's generally better to use a `useEffect` for such purposes.
893893+For simpler implementations, consider using `useScrollViewOffset`.
16018941602895### Platform Compatibility
1603896···1605898|-|-|-|
1606899|✅|✅|✅|
160790016081608-````markdown
16091609-# withSequence
901901+This documentation provides a comprehensive overview of how to utilize the `useHandler` hook within React Native Reanimated for creating custom event handlers.
902902+903903+## Keyframe animations
161090416111611-`withSequence` is an animation modifier that allows animations to be executed in a sequential order.
905905+Keyframes provide a schema for defining animations, offering more flexibility than standard Entering and Exiting presets. They allow you to create complex animations with ease.
161290616131613-## Reference
907907+### Reference
16149081615909```typescript
16161616-import { withSequence } from "react-native-reanimated"
910910+import { Keyframe } from 'react-native-reanimated';
911911+912912+const keyframe = new Keyframe({
913913+ 0: {
914914+ transform: [{ rotate: '0deg' }],
915915+ },
916916+ 45: {
917917+ transform: [{ rotate: '100deg' }],
918918+ easing: Easing.exp,
919919+ },
920920+ 100: {
921921+ transform: [{ rotate: '45deg' }],
922922+ },
923923+});
16179241618925function App() {
16191619- sv.value = withSequence(withTiming(50), withTiming(0))
16201620- // ...
926926+ return <Animated.View entering={keyframe} />;
1621927}
1622928```
16231623-````
16249291625930#### Arguments
162693116271627-##### `reduceMotion` (Optional)
932932+##### `definitions`
162893316291629-A parameter that specifies how the animation should respond to the device's reduced motion accessibility setting.
934934+An 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.
163093516311631-##### `...animations`
936936+Key values include:
163293716331633-Any number of animation objects that will be executed in sequence.
16341634-16351635-#### Returns
938938+- `0` or `from`: Represents the initial state.
939939+- Intermediate points (e.g., `45`): Represent intermediate states.
940940+- `100` or `to`: Represents the final state.
163694116371637-The `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`.
942942+The key `0` (or `from`) should define the style at the start of the animation, while `100` (or `to`) defines it at the end.
163894316391639-### Example
16401640-16411641-### Platform Compatibility
16421642-16431643-|Android|iOS|Web|
16441644-|-|-|-|
16451645-|✅|✅|✅|
16461646-16471647-````
16481648-16491649-# useFrameCallback in React Native Reanimated (Version: 3.x)
16501650-16511651-## Overview
16521652-16531653-The `useFrameCallback` hook allows you to execute a function on every frame update within your application.
16541654-16551655-## Reference
944944+### Modifiers
16569451657946```typescript
16581658-import { useFrameCallback } from 'react-native-reanimated';
947947+keyframe
948948+ .duration(1000)
949949+ .delay(500)
950950+ .reduceMotion(ReduceMotion.Never)
951951+ .withCallback((finished) => {
952952+ console.log(`finished without interruptions: ${finished}`)
953953+ })
954954+```
165995516601660-function App() {
16611661- const frameCallback = useFrameCallback((frameInfo) => {
16621662- // Increment a value with each frame update
16631663- sv.value += 1;
16641664- });
16651665-16661666- return (
16671667- <Button
16681668- title="Start/Stop"
16691669- onPress={() => frameCallback.setActive(!frameCallback.isActive)}
16701670- />
16711671- );
16721672-}
16731673-````
16741674-16751675-#### Arguments
16761676-16771677-##### `callback`
16781678-16791679-- A function that runs on every frame update.
16801680-- Receives a `frameInfo` object with the following properties:
16811681- - `timestamp`: The system time (in milliseconds) when the last frame was rendered.
16821682- - `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.
16831683- - `timeSinceFirstFrame`: The time (in milliseconds) elapsed since the callback was activated.
16841684-16851685-##### `autostart` (Optional)
16861686-16871687-- Determines if the callback should start automatically. Defaults to `true`.
16881688-16891689-#### Returns
16901690-16911691-The `useFrameCallback` hook returns an object with these properties:
16921692-16931693-- `setActive`: A function to start or stop the frame callback.
16941694-- `isActive`: A boolean indicating whether the callback is currently running.
16951695-- `callbackId`: A unique identifier for the frame callback.
956956+- `.duration(durationMs: number)` sets the animation length in milliseconds, defaulting to `500`.
957957+- `.delay(durationMs: number)` specifies a delay before starting the animation, defaulting to `0`.
958958+- `.reduceMotion(reduceMotion: ReduceMotion)` adjusts the animation based on the device's reduced motion setting.
959959+- `.withCallback(callback: (finished: boolean) => void)` triggers after the animation ends, indicating if it finished without interruptions.
16969601697961### Remarks
169896216991699-- The function provided in the `callback` argument is automatically workletized and executed on the UI thread.
963963+- Providing keyframe `0` or `from` is mandatory as it defines the initial state of the object to be animated.
964964+- Ensure all style properties intended for animation have an initial value in other keyframes.
965965+- Easing should only be applied to subsequent keyframes, not to keyframe `0`.
966966+- Avoid using both `0` and `from`, or `100` and `to`, as it causes parsing conflicts.
967967+- When animating transform styles, maintain the order of properties consistently across all keyframes.
17009681701969### Platform Compatibility
1702970···1704972|-|-|-|
1705973|✅|✅|✅|
170697417071707-- Reference
17081708- - Arguments
17091709- - Returns
17101710-- Example
17111711-- Remarks
17121712-- Platform compatibility
975975+## Your First Animation
976976+977977+This 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.
171397817141714-## Reduced Motion Configuration
979979+### Using an Animated Component
171598017161716-The `ReducedMotionConfig` component allows you to modify behavior based on the device's reduced motion accessibility setting. By default, it disables all animations when reduced motion is enabled on a device. You can customize this for your specific needs. For more information, refer to Accessibility and `useReducedMotion` in Reanimated.
981981+To start animating components in React Native using Reanimated, import the `Animated` object:
17179821718983```typescript
17191719-interface ReducedMotionConfig {
17201720- // Define properties or methods as needed
17211721-}
984984+import Animated from "react-native-reanimated"
1722985```
172398617241724-This component helps ensure that your application respects user preferences regarding motion settings.
17251725-17261726-## Glossary of Terms
17271727-17281728-### Animated Component
17291729-17301730-Animated components are those that can be animated using Reanimated. The library includes built-in components such as `Animated.View`, `Animated.Text`, and `Animated.ScrollView`.
987987+The `Animated` object wraps native components like `View`, `ScrollView`, or `FlatList`. Use these components as you would any other JSX component:
17319881732989```typescript
1733990import Animated from 'react-native-reanimated';
173499117351735-function App() {
992992+export default function App() {
1736993 return (
1737994 <Animated.View
1738995 style={{
···17451002}
17461003```
1747100417481748-For components not included in Reanimated, you can make their props and styles animatable by wrapping them with `createAnimatedComponent`:
10051005+### Defining a Shared Value
1749100617501750-```typescript
17511751-import Animated from "react-native-reanimated"
17521752-import { Circle } from "react-native-svg"
17531753-17541754-const AnimatedCircle = Animated.createAnimatedComponent(Circle)
17551755-```
17561756-17571757-### Shared Value
17581758-17591759-Shared values are essential for animations in Reanimated. They are defined using the `useSharedValue` hook and accessed or modified via their `.value` property.
10071007+Shared values are essential for animations, acting like React state synchronized between JavaScript and the native side. Create shared values using `useSharedValue`:
1760100817611009```typescript
17621010import { useSharedValue } from "react-native-reanimated"
17631763-17641764-function App() {
17651765- const sv = useSharedValue(0)
17661766-17671767- const handlePress = () => {
17681768- sv.value += 10
17691769- }
17701770-17711771- // rest of your glamorous code ✨
17721772-}
17731011```
1774101217751775-Shared values can store any type and automatically synchronize data between the JavaScript thread and the UI thread.
17761776-17771777-### Animatable Value
17781778-17791779-An 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.
17801780-17811781-### Animation Function
17821782-17831783-Animation functions define how animations should behave. Reanimated provides three built-in animation functions:
17841784-17851785-- `withSpring`: Creates spring-based animations.
17861786-- `withTiming`: Creates duration and easing-based animations.
17871787-- `withDecay`: Mimics motion with a given deceleration rate.
17881788-17891789-These can be combined with modifiers for complex animations.
17901790-17911791-### Animation Modifier
17921792-17931793-Animation modifiers customize animations. Known as higher-order animations, Reanimated includes:
17941794-17951795-- `withDelay`: Adds a delay before the animation starts.
17961796-- `withRepeat`: Repeats an animation a specified number of times.
17971797-- `withSequence`: Chains animations sequentially.
17981798-- `withClamp`: Limits animation boundaries to a specific range.
17991799-18001800-### Animation Object
18011801-18021802-An 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.
18031803-18041804-When passed to a shared value, it is treated as an animatable value:
18051805-18061806-```typescript
18071807-sv.value = withSpring(100)
18081808-```
18091809-18101810-### Animations in Inline Styling
18111811-18121812-Shared values can be directly used in the `style` property without `useAnimatedStyle`.
18131813-18141814-Example:
18151815-18161816-```typescript
18171817-function App() {
18181818- const width = useSharedValue(100);
18191819-18201820- return <Animated.View style={{ width }} />;
18211821-}
18221822-```
18231823-18241824-### Layout Animation Modifier
18251825-18261826-Layout animation modifiers customize layout animations. Example usage:
18271827-18281828-```typescript
18291829-<Animated.View entering={FadeOutLeft.duration(500).easing(Easing.ease)} />
18301830-```
18311831-18321832-Built-in modifiers include:
18331833-18341834-- `.duration(durationMs: number)`: Sets the animation length in milliseconds.
18351835-- `.easing(easingFunction: EasingFunction)`: Defines the animation curve.
18361836-- `.springify()`: Enables spring-based animations.
18371837-- `.damping(value: number)`: Controls how quickly a spring stops moving.
18381838-- `.withCallback(callback: (finished: boolean) => void)`: Triggers after the animation ends.
18391839-18401840-### Worklet
18411841-18421842-Worklets are short-running JavaScript functions executed on the UI thread. They can also run on the JavaScript thread like regular functions.
18431843-18441844-Code is often automatically workletized and runs on the UI thread by default:
18451845-18461846-```typescript
18471847-const style = useAnimatedStyle(() => {
18481848- console.log("Running on the UI thread")
18491849- return { opacity: 0.5 }
18501850-})
18511851-```
18521852-18531853-Custom worklets can be created using the `"worklet";` directive:
18541854-18551855-```typescript
18561856-function myWorklet() {
18571857- "worklet"
18581858- console.log("Running on the UI thread")
18591859-}
18601860-```
18611861-18621862-Use `runOnUI` to manually execute worklets on the UI thread:
18631863-18641864-```typescript
18651865-function myWorklet(greeting) {
18661866- "worklet"
18671867- console.log(`${greeting} from the UI thread`)
18681868-}
18691869-18701870-function onPress() {
18711871- runOnUI(myWorklet)("Howdy")
18721872-}
18731873-```
18741874-18751875-### To Workletize
18761876-18771877-Converts 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.
18781878-18791879-### JavaScript Thread
18801880-18811881-The JavaScript thread handles code execution in the app, serving as the primary location for React Native app code execution.
18821882-18831883-### UI Thread
18841884-18851885-The 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.
18861886-18871887-### Reanimated Babel Plugin
18881888-18891889-This plugin automatically workletizes certain functions used with Reanimated, reducing boilerplate code. Details are available in the Reanimated Babel plugin README.
18901890-18911891-## withDelay
10131013+Define shared values within your component's body to store any JS value or data structure.
1892101418931893-`withDelay` is an animation modifier that allows you to initiate an animation after a specified delay period.
18941894-18951895-### Reference
10151015+For example, set a default value of `100` for width in an `Animated.View`:
1896101618971017```typescript
18981898-import { withDelay } from "react-native-reanimated"
18991899-19001900-function App() {
19011901- sv.value = withDelay(500, withTiming(0))
19021902- // ...
19031903-}
19041904-```
19051905-19061906-#### Arguments
19071907-19081908-- **`delayMs`**: Specifies the duration (in milliseconds) before the animation begins.
19091909-19101910-- **`delayedAnimation`**: The animation that will be delayed.
19111911-19121912-- **`reduceMotion`** *(Optional)*: Determines how the animation responds to the device's reduced motion accessibility setting.
19131913-19141914-#### Returns
19151915-19161916-The `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`.
19171917-19181918-### Example
19191919-19201920-*(Example content would go here)*
19211921-19221922-### Platform Compatibility
19231923-19241924-|Android|iOS|Web|
19251925-|-|-|-|
19261926-|✅|✅|✅|
19271927-19281928-***
19291929-19301930-## useAnimatedKeyboard in React Native Reanimated (Version: 3.x)
19311931-19321932-### Overview
19331933-19341934-The `useAnimatedKeyboard` hook allows developers to create animations that respond to the state and height of the virtual keyboard.
19351935-19361936-> **Caution:**\
19371937-> The Android implementation of `useAnimatedKeyboard` has limitations on devices running Android SDK versions below 30. For more details, refer to the remarks section.
19381938-19391939-### Reference
19401940-19411941-```typescript
19421942-import { useAnimatedKeyboard, useAnimatedStyle } from "react-native-reanimated"
10181018+import Animated, { useSharedValue } from 'react-native-reanimated';
1943101919441020export default function App() {
19451945- const keyboard = useAnimatedKeyboard()
19461946-19471947- const animatedStyles = useAnimatedStyle(() => ({
19481948- transform: [{ translateY: -keyboard.height.value }],
19491949- }))
19501950-}
19511951-```
19521952-19531953-#### Arguments
19541954-19551955-##### `options` (Optional)
19561956-19571957-An optional configuration object that includes:
19581958-19591959-- **isStatusBarTranslucentAndroid**:\
19601960- Removes the top inset on Android when set to `true`, allowing for a translucent status bar. Defaults to `false`. This option is ignored on iOS.
19611961-19621962-#### Returns
19631963-19641964-The `useAnimatedKeyboard` hook returns an object with the following fields:
19651965-19661966-|Name|Type|Description|
19671967-|-|-|-|
19681968-|height|`SharedValue<number>`|A shared value representing the current height of the keyboard.|
19691969-|state|`SharedValue<KeyboardState>`|A shared value indicating the current state of the keyboard. Possible states: `{ CLOSED, OPEN, CLOSING, OPENING }`|
19701970-19711971-### Remarks
19721972-19731973-- **Android Specifics**:\
19741974- Ensure that `android:windowSoftInputMode` is set to `adjustResize` in your `AndroidManifest.xml`. This setting disables the default Android behavior (resizing the view for keyboard accommodation) across the app. By using values from the `useAnimatedKeyboard` hook, you can manage the keyboard manually. Unmounting all components that use this hook will revert to the default Android behavior.
19751975-19761976-- **Root View Management**:\
19771977- On Android, employing the `useAnimatedKeyboard` hook expands the root view to full screen (immersive mode) and manages insets:
19781978-19791979- - With `isStatusBarTranslucentAndroid` set to `false`, it applies a top margin based on the insets.
19801980- - When `true`, it sets the top margin to `0`.
19811981- - Similarly, with `isNavigationBarTranslucentAndroid`:
19821982- - `false`: Applies bottom margin according to the insets.
19831983- - `true`: Sets bottom margin to `0`.
19841984-19851985-- **Native Header Navigation**:\
19861986- On Android, using native header navigation means that `isStatusBarTranslucentAndroid` does not affect the top inset.
19871987-19881988-- **SDK Limitations**:\
19891989- For devices running Android SDK versions below 30, if the status bar is hidden, the keyboard reverts to default Android behavior.
19901990-19911991-### Platform Compatibility
19921992-19931993-|Android|iOS|Web|
19941994-|-|-|-|
19951995-|✅|✅|❌|
19961996-19971997-- **Reference**
19981998-19991999- - Arguments
20002000- - Returns
20012001-20022002-- **Example**
20032003-20042004-- **Remarks**
20052005-20062006-- **Platform Compatibility**
20072007-20082008-## useComposedEventHandler Hook
20092009-20102010-The `useComposedEventHandler` hook allows you to combine multiple event handlers, such as those created with `useAnimatedScrollHandler`, into a single handler.
20112011-20122012-### Reference Example
20132013-20142014-```typescript
20152015-import Animated, {
20162016- useAnimatedScrollHandler,
20172017- useComposedEventHandler,
20182018-} from 'react-native-reanimated';
20192019-20202020-function ComposedEventHandlerExample() {
20212021- const onScrollHandler1 = useAnimatedScrollHandler({
20222022- onScroll(e) {
20232023- console.log('Scroll handler 1 onScroll event');
20242024- },
20252025- });
20262026-20272027- const onScrollHandler2 = useAnimatedScrollHandler({
20282028- onScroll(e) {
20292029- console.log('Scroll handler 2 onScroll event');
20302030- },
20312031- });
20322032-20332033- const composedHandler = useComposedEventHandler([
20342034- onScrollHandler1,
20352035- onScrollHandler2,
20362036- ]);
10211021+ const width = useSharedValue(100);
2037102220381023 return (
20392039- <View style={styles.container}>
20402040- <Animated.ScrollView style={styles.scroll} onScroll={composedHandler}>
20412041- <Content />
20422042- </Animated.ScrollView>
20432043- </View>
10241024+ <Animated.View
10251025+ style={{
10261026+ width,
10271027+ height: 100,
10281028+ backgroundColor: 'violet',
10291029+ }}
10301030+ />
20441031 );
20451032}
20461033```
2047103420482048-#### Arguments
20492049-20502050-- **`handlers`**: An array of event handlers created using the `useEvent` hook. The `useComposedEventHandler` hook updates whenever there are changes in these handlers.
20512051-20522052-#### Returns
20532053-20542054-The 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.
20552055-20562056-### Remarks
20572057-20582058-- 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.
20592059-- It functions effectively when used with multiple `Animated components`, triggering event callbacks for each connected component.
20602060-20612061-### Platform Compatibility
20622062-20632063-|Android|iOS|Web|
20642064-|-|-|-|
20652065-|✅|✅|✅|
20662066-20672067-## dispatchCommand
20682068-20692069-The `dispatchCommand` function enables the execution of commands directly on a native component from the UI thread.
20702070-20712071-### Reference
20722072-20732073-```typescript
20742074-import { dispatchCommand } from 'react-native-reanimated';
20752075-20762076-function App() {
20772077- const animatedRef = useAnimatedRef();
20782078-20792079- const gesture = Gesture.Tap().onStart(() => {
20802080- dispatchCommand(animatedRef, 'focus');
20812081- });
20822082-20832083- return (
20842084- <>
20852085- <AnimatedTextInput ref={animatedRef} style={styles.input} />
20862086- <GestureDetector gesture={gesture}>
20872087- <Button title="Focus" />
20882088- </GestureDetector>
20892089- </>
20902090- );
20912091-}
20922092-```
20932093-20942094-#### Arguments
20952095-20962096-- **`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.
20972097-20982098-- **`commandName`**: The name of the command to execute, such as `'focus'` or `'scrollToEnd'`.
20992099-21002100-- **`args` (Optional)**: An array of arguments for the command. Defaults to an empty array if not provided.
21012101-21022102-### Example
21032103-21042104-```typescript
21052105-const goDown = Gesture.Tap().onStart(() => {
21062106- dispatchCommand(tosRef, "scrollToEnd", [true])
21072107- dispatchCommand(loginRef, "focus")
21082108-})
21092109-```
21102110-21112111-### Remarks
21122112-21132113-- Commands vary depending on the component. Refer to the relevant React Native documentation for available commands specific to each component.
21142114-21152115-### Platform Compatibility
21162116-21172117-|Android|iOS|Web|
21182118-|-|-|-|
21192119-|✅|✅|❌|
21202120-21212121-## withClamp
21222122-21232123-`withClamp` is an animation modifier that restricts the movement of your animation within a specified range. It's typically used in conjunction with `withSpring`.
21242124-21252125-### Reference
21262126-21272127-```typescript
21282128-import { withClamp } from "react-native-reanimated"
21292129-21302130-function App() {
21312131- sv.value = withClamp({ min: -1, max: 1 }, withSpring(0))
21322132- // ...
21332133-}
21342134-```
21352135-21362136-#### Arguments
21372137-21382138-##### `config`
21392139-21402140-An object containing the following properties:
21412141-21422142-|Name|Type|Description|
21432143-|-|-|-|
21442144-|min|number|Optional. The lowest value your animation can reach.|
21452145-|max|number|Optional. The highest value your animation can reach.|
21462146-21472147-##### `animation`
21482148-21492149-The spring animation you wish to clamp.
21502150-21512151-```typescript
21522152-const clampedStyleWithDelay = useAnimatedStyle(() => {
21532153- return {
21542154- width: withClamp({ min: 0, max: 100 }, withSpring(randomWidth.value)),
21552155- }
21562156-})
21572157-```
21582158-21592159-#### Returns
21602160-21612161-`withClamp` returns an animation object. This can be directly assigned to a shared value or used as a style value in `useAnimatedStyle`.
21622162-21632163-|Platform|Supported|
21642164-|-|-|
21652165-|Android|✅|
21662166-|iOS|✅|
21672167-|Web|✅|
21682168-21692169-## useAnimatedSensor
21702170-21712171-`useAnimatedSensor` allows you to create animations based on device sensor data. It provides access to:
21722172-21732173-- **Accelerometer**: Measures device acceleration (excluding gravity) along the x, y, and z axes.
21742174-- **Gyroscope**: Captures the rotation rate of the device along the x, y, and z axes.
21752175-- **Gravity**: Provides the current gravity vector along the x, y, and z axes.
21762176-- **Magnetic Field**: Measures the Earth's magnetic field strength and direction in microtesla (μT).
21772177-- **Rotation**: Represents the device orientation using Euler angles and a quaternion.
21782178-21792179-For comprehensive documentation, refer to the Sensors guide on Android Developers and Device Motion in Apple Developer documentation.
21802180-21812181-### Reference
21822182-21832183-```typescript
21842184-import { useAnimatedSensor, SensorType } from "react-native-reanimated"
21852185-21862186-function App() {
21872187- const gyroscope = useAnimatedSensor(SensorType.GYROSCOPE)
21882188-21892189- useDerivedValue(() => {
21902190- const { x, y, z } = gyroscope.sensor.value
21912191- })
21922192-}
21932193-```
21942194-21952195-#### Arguments
21962196-21972197-##### `sensorType`
21982198-21992199-Specifies the sensor type using a `SensorType` enum:
22002200-22012201-- `ACCELEROMETER`: Measures device acceleration in m/s².
22022202-- `GYROSCOPE`: Captures rotation rate in radians per second.
22032203-- `GRAVITY`: Provides gravity vector in m/s².
22042204-- `MAGNETIC_FIELD`: Measures magnetic field strength in microtesla (μT).
22052205-- `ROTATION`: Represents orientation using Euler angles and a quaternion.
22062206-22072207-##### `config` (Optional)
22082208-22092209-|Name|Type|Default|Description|
22102210-|-|-|-|-|
22112211-|interval|`number \| "auto"`|`"auto"`|Time between sensor readings in milliseconds. `"auto"` matches the device's screen refresh rate.|
22122212-|adjustToInterfaceOrientation|`boolean`|`true`|Adjusts measurements to the current interface orientation.|
22132213-|iosReferenceFrame|`IOSReferenceFrame`|`IOSReferenceFrame.Auto`|Frame of reference for iOS sensors.|
22142214-22152215-Available `IOSReferenceFrame` options:
22162216-22172217-- `xArbitraryZVertical`: Z axis is vertical, X axis arbitrary in horizontal plane.
22182218-- `xArbitraryCorrectedZVertical`: Improved rotation accuracy with Z vertical and X arbitrary.
22192219-- `XMagneticNorthZVertical`: Z axis vertical, X points to magnetic north.
22202220-- `XTrueNorthZVertical`: Z axis vertical, X points to geographic north.
22212221-- `Auto`: Defaults based on device capabilities.
22222222-22232223-#### Returns
22242224-22252225-`useAnimatedSensor` returns an object:
22262226-22272227-|Name|Type|Description|
22282228-|-|-|-|
22292229-|sensor|`SharedValue<Value3D \| ValueRotation>`|Shared value with sensor measurements.|
22302230-|unregister|`() => void`|Stops listening to sensor updates when called.|
22312231-|isAvailable|`boolean`|Indicates if the sensor is available for use.|
22322232-|config|`SensorConfig`|Contains sensor configuration details.|
22332233-22342234-The shared value from the **rotation sensor** includes:
22352235-22362236-- Euler angles: `roll`, `pitch`, `yaw`.
22372237-- Quaternion components: `qw`, `qx`, `qy`, `qz`.
22382238-- Interface orientation.
22392239-22402240-Other sensors return measurements on x, y, z axes and interface orientation.
22412241-22422242-`InterfaceOrientation` enum values:
22432243-22442244-- `ROTATION_0`: Default rotation on Android, portrait on iOS.
22452245-- `ROTATION_90`: 90 degrees on Android, landscape right on iOS.
22462246-- `ROTATION_180`: 180 degrees on Android, upside down on iOS.
22472247-- `ROTATION_270`: 270 degrees on Android, landscape left on iOS.
22482248-22492249-### Example
22502250-22512251-```typescript
22522252-export default function App() {
22532253- const gravity = useAnimatedSensor(SensorType.GRAVITY);
22542254-22552255- const animatedStyle = useAnimatedStyle(() => {
22562256- return {
22572257- transform: [
22582258- { translateX: withSpring(gravity.sensor.value.x * 20) },
22592259- { translateY: withSpring(gravity.sensor.value.y * 20) },
22602260- ],
22612261- };
22622262- });
22632263-22642264- return (
22652265- <View style={styles.container}>
22662266- <Animated.View style={[styles.box, animatedStyle]} />
22672267- </View>
22682268- );
22692269-}
22702270-```
22712271-22722272-### Remarks
22732273-22742274-- On iOS, enable location services (`Settings > Privacy > Location Services`) to read sensor data.
22752275-- On Web, ensure the device supports sensors and the application is served over HTTPS.
22762276-- Most sensors operate at resolutions up to 100Hz.
22772277-- Sensor data can be accessed on both UI and JavaScript threads.
22782278-22792279-### Platform Compatibility
22802280-22812281-|Android|iOS|Web|
22822282-|-|-|-|
22832283-|✅|✅|✅|
22842284-22852285-## setNativeProps
22862286-22872287-The `setNativeProps` function allows for the imperative updating of component properties in React Native. It serves as an escape hatch intended for specific edge cases.
22882288-22892289-> **Caution:**\
22902290-> Prefer using `useAnimatedStyle` and `useAnimatedProps` when animating styles or properties, reserving `setNativeProps` for exceptional situations.
22912291-22922292-### Reference
22932293-22942294-```typescript
22952295-import { setNativeProps } from 'react-native-reanimated';
22962296-22972297-function App() {
22982298- const animatedRef = useAnimatedRef();
22992299-23002300- const tap = Gesture.Tap().onEnd(() => {
23012301- setNativeProps(animatedRef, { text: '' });
23022302- });
23032303-23042304- return <TextInput ref={animatedRef} />;
23052305-}
23062306-```
23072307-23082308-#### Arguments
23092309-23102310-- **`animatedRef`:**\
23112311- 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.
23122312-23132313-- **`updates`:**\
23142314- An object containing properties that need updating, which can include both style properties (e.g., `width`, `backgroundColor`) and regular properties (e.g., `text`).
23152315-23162316-#### Returns
23172317-23182318-The function returns `undefined`.
23192319-23202320-### Remarks
23212321-23222322-- Prioritize using `useAnimatedStyle` and `useAnimatedProps` for animating styles or properties.
23232323-- Ensure that `setNativeProps` is used exclusively on the UI thread.
23242324-- 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.
23252325-23262326-### Platform Compatibility
23272327-23282328-|Android|iOS|Web|
23292329-|-|-|-|
23302330-|✅|✅|✅|
23312331-23322332-***
23332333-23342334-## React Native Reanimated: useReducedMotion Hook (Version 3.x)
23352335-23362336-### Overview
23372337-23382338-The `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.
23392339-23402340-### Reference
23412341-23422342-```typescript
23432343-import { useReducedMotion } from "react-native-reanimated"
23442344-23452345-function App() {
23462346- const reduceMotion = useReducedMotion()
23472347-23482348- if (reduceMotion) {
23492349- // Display static content ✨
23502350- } else {
23512351- // Run animations ✨
23522352- }
23532353-23542354- // Additional logic...
23552355-}
23562356-```
23572357-23582358-#### Returns
23592359-23602360-The `useReducedMotion` hook returns a boolean value indicating whether the reduced motion setting was enabled at the start of the app.
23612361-23622362-### Example Usage
23632363-23642364-```typescript
23652365-import { useReducedMotion } from 'react-native-reanimated';
23662366-23672367-function App() {
23682368- const reduceMotion = useReducedMotion();
23692369-23702370- if (reduceMotion) {
23712371- return <StaticContent />;
23722372- } else {
23732373- return <AnimatedContent />;
23742374- }
23752375-}
23762376-```
23772377-23782378-### Remarks
23792379-23802380-- Changing the reduced motion setting does not trigger a component rerender.
23812381-- Unlike `AccessibilityInfo.isReduceMotionEnabled()`, `useReducedMotion` provides the value synchronously.
23822382-23832383-### Platform Compatibility
23842384-23852385-|Android|iOS|Web|
23862386-|-|-|-|
23872387-|✅|✅|✅|
23882388-23892389-This hook is compatible across Android, iOS, and Web platforms.
23902390-23912391-## makeMutable
23922392-23932393-**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).
23942394-23952395-Internally, `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.
23962396-23972397-The object produced by `makeMutable` mirrors that returned by the `useSharedValue` hook, ensuring consistent usage thereafter.
23982398-23992399-### Reference
24002400-24012401-```typescript
24022402-import { makeMutable } from "react-native-reanimated"
24032403-24042404-const mv = makeMutable(100)
24052405-```
24062406-24072407-#### Arguments
24082408-24092409-##### `initial`
24102410-24112411-This 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.
24122412-24132413-#### Returns
24142414-24152415-`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.
24162416-24172417-### Example
24182418-24192419-### Remarks
24202420-24212421-**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.
24222422-24232423-- All remarks applicable to the `useSharedValue` hook are relevant to `makeMutable`.
24242424-- Avoid invoking `makeMutable` directly within component scope. Component re-renders will generate a new object, potentially resetting the initial value and losing previous state.
24252425-24262426-```typescript
24272427-function App() {
24282428- const [counter, setCounter] = useState(0)
24292429- const mv = makeMutable(counter) // 🚨 creates a new mutable value on each render
24302430-24312431- useEffect(() => {
24322432- const interval = setInterval(() => {
24332433- setCounter((prev) => prev + 1) // updates the counter stored in component state
24342434- }, 1000)
24352435-24362436- return () => {
24372437- clearInterval(interval)
24382438- }
24392439- }, [mv])
24402440-24412441- useAnimatedReaction(
24422442- () => mv.value,
24432443- (value) => {
24442444- console.log(value) // prints 0, 1, 2, ...
24452445- }
24462446- )
24472447-}
24482448-```
24492449-24502450-- 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.
24512451-24522452-```typescript
24532453-function App() {
24542454- const mv = useMemo(() => makeMutable(0), [])
24552455-24562456- useEffect(() => {
24572457- mv.value = withRepeat(withSpring(100), -1, true) // creates an infinite animation
24582458-24592459- return () => {
24602460- cancelAnimation(mv) // ✅ stops the infinite animation on component unmount
24612461- }
24622462- }, [])
24632463-}
24642464-```
24652465-24662466-- `cancelAnimation` is not needed for non-animated values as they are automatically garbage collected when no references remain.
24672467-24682468-```typescript
24692469-const someFlag = makeMutable(false)
24702470-24712471-function App() {
24722472- someFlag.value = true // ✅ no need to cancel the animation later on
24732473-}
24742474-```
24752475-24762476-- 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).
24772477-24782478-#### Comparison with `useSharedValue`
24792479-24802480-|Feature|`makeMutable`|`useSharedValue`|
24812481-|-|-|-|
24822482-|Object Creation|Creates a new object on each call|Reuses the same object on each call|
24832483-|Initial Value Change|A new object is created if `initial` changes|The initially created object remains unchanged if `initialValue` changes|
24842484-|Scope Usage|Can be used outside of component scope|Limited to use within component scope|
24852485-|Loop Usage|Usable in loops with variable iterations|Usable in loops only if the number of hooks (`useSharedValue` calls) is constant|
24862486-|Animation Cancellation|Does not automatically cancel animations on unmount|Automatically cancels animations when the component unmounts|
10351035+### Using a Shared Value
2487103624882488-### Platform Compatibility
10371037+Create 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.
2489103824902490-|Android|iOS|Web|
24912491-|-|-|-|
24922492-|✅|✅|✅|
24932493-24942494-## Accurate Call Stacks
24952495-24962496-When debugging Reanimated code, you might come across error or warning call stacks that do not clearly point to the root cause of an issue. These stacks can be misleading because they frequently emphasize code from Reanimated's internal workings instead of highlighting the misuse of the Reanimated API, which is often the actual source of the problem.
10391039+Access and modify values stored in shared values using their `.value` property:
2497104024981041```typescript
24992499-// Example TypeScript snippet for context (not part of original content)
25002500-function debugReanimatedCode() {
25012501- // Debugging logic here
25022502-}
25032503-```
25042504-25052505-|Aspect|Description|
25062506-|-|-|
25072507-|**Issue**|Misleading call stacks in error or warning messages.|
25082508-|**Cause**|Call stacks often highlight Reanimated's internal code rather than API misuse.|
25092509-|**Impact**|Difficulty in identifying the true source of problems during debugging.|
25102510-25112511-Understanding this behavior is crucial for effectively diagnosing and resolving issues within Reanimated projects.
25122512-25132513-## Animating Styles and Props
25142514-25152515-In this section, we explore different methods for passing animation styles to components. We will differentiate between animating styles and props using `useAnimatedStyle` and `useAnimatedProps`.
25162516-25172517-### Animating Styles
25182518-25192519-Previously, 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.
25202520-25212521-```typescript
10421042+import { Button, View } from 'react-native';
25221043import Animated, { useSharedValue } from 'react-native-reanimated';
2523104425242524-function App() {
10451045+export default function App() {
25251046 const width = useSharedValue(100);
2526104725272527- return <Animated.View style={{ width }} />;
25282528-}
25292529-```
25302530-25312531-For example, multiplying a shared value before assigning it to the `style` prop is not possible:
25322532-25332533-```typescript
25342534-<Animated.View style={{ width: width * 5 }} /> // This won't work
25352535-```
25362536-25372537-Consider an example where a box moves right on button press:
25382538-25392539-```typescript
25402540-import { View, Button } from 'react-native';
25412541-import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
25422542-25432543-function App() {
25442544- const translateX = useSharedValue(0);
25452545-25461048 const handlePress = () => {
25472547- translateX.value = withSpring(translateX.value + 50);
10491049+ width.value = width.value + 50;
25481050 };
2549105125501052 return (
25512551- <View style={styles.container}>
25522552- <Animated.View style={[styles.box, { transform: [{ translateX }] }]} />
10531053+ <View style={{ flex: 1, alignItems: 'center' }}>
10541054+ <Animated.View
10551055+ style={{
10561056+ width,
10571057+ height: 100,
10581058+ backgroundColor: 'violet',
10591059+ }}
10601060+ />
25531061 <Button onPress={handlePress} title="Click me" />
25541062 </View>
25551063 );
25561064}
25571065```
2558106625592559-To customize shared value changes based on user input, `useAnimatedStyle` is used for more control and flexibility:
25602560-25612561-```typescript
25622562-export default function App() {
25632563- const translateX = useSharedValue<number>(0);
10671067+Avoid directly modifying shared values without using the `.value` property, as in `sv.value = sv.value + 100`.
2564106825652565- const handlePress = () => {
25662566- translateX.value += 50;
25672567- };
10691069+### Using an Animation Function
2568107025692569- const animatedStyles = useAnimatedStyle(() => ({
25702570- transform: [{ translateX: withSpring(translateX.value * 2) }],
25712571- }));
25722572-25732573- return (
25742574- <>
25752575- <Animated.View style={[styles.box, animatedStyles]} />
25762576- <View style={styles.container}>
25772577- <Button onPress={handlePress} title="Click me" />
25782578- </View>
25792579- </>
25802580- );
25812581-}
25822582-```
25832583-25842584-`useAnimatedStyle` allows access to the shared value's `.value`, enabling operations like multiplication before assigning it to `style`. It also centralizes animation logic.
25852585-25862586-### Animating Props
25872587-25882588-While many values are animated via the `style` property, sometimes props need animating. For example, SVG elements use props instead of styles:
10711071+To animate smoothly, import and use the `withSpring` function. Wrap it around the new width value to create a spring animation:
2589107225901073```typescript
25912591-<Circle cx="50" cy="50" r="10" fill="blue" />
25922592-```
25932593-25942594-To animate non-Reanimated components' props, wrap them with `createAnimatedComponent`:
25952595-25962596-```typescript
25972597-import Animated from "react-native-reanimated"
25982598-import { Circle } from "react-native-svg"
25992599-26002600-const AnimatedCircle = Animated.createAnimatedComponent(Circle)
26012601-```
26022602-26032603-Animating the radius of an SVG circle can be done by passing a shared value as a prop:
26042604-26052605-```typescript
26062606-import { useSharedValue } from 'react-native-reanimated';
26072607-import { Svg } from 'react-native-svg';
26082608-26092609-function App() {
26102610- const r = useSharedValue(10);
26112611-26122612- return (
26132613- <Svg>
26142614- <AnimatedCircle cx="50" cy="50" r={r} fill="blue" />
26152615- </Svg>
26162616- );
26172617-}
26182618-```
26192619-26202620-For encapsulating animation logic and accessing `.value`, `useAnimatedProps` is used:
26212621-26222622-```typescript
26232623-const AnimatedCircle = Animated.createAnimatedComponent(Circle);
10741074+import { Button, View } from 'react-native';
10751075+import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
2624107626251077export default function App() {
26262626- const r = useSharedValue<number>(20);
10781078+ const width = useSharedValue(100);
2627107926281080 const handlePress = () => {
26292629- r.value += 10;
10811081+ width.value = withSpring(width.value + 50);
26301082 };
2631108326322632- const animatedProps = useAnimatedProps(() => ({
26332633- r: withTiming(r.value),
26342634- }));
26352635-26361084 return (
26372637- <View style={styles.container}>
26382638- <Svg style={styles.svg}>
26392639- <AnimatedCircle
26402640- cx="50%"
26412641- cy="50%"
26422642- fill="#b58df1"
26432643- animatedProps={animatedProps}
26442644- />
26452645- </Svg>
10851085+ <View style={{ flex: 1, alignItems: 'center' }}>
10861086+ <Animated.View
10871087+ style={{
10881088+ width,
10891089+ height: 100,
10901090+ backgroundColor: 'violet',
10911091+ }}
10921092+ />
26461093 <Button onPress={handlePress} title="Click me" />
26471094 </View>
26481095 );
26491096}
26501097```
2651109826522652-In `useAnimatedProps`, return an object with animatable props, then pass it to the `animatedProps` prop of an Animated component.
10991099+This creates a bouncy spring animation for the element's width.
2653110026541101### Summary
2655110226562656-- Inline styles are simple but limited for complex animations.
26572657-- Props differ from styles as they aren't passed via the `style` object.
26582658-- `useAnimatedStyle` and `useAnimatedProps` provide access to shared values' `.value`, enhancing animation control.
26592659-- Custom animatable components can be created with `Animated.createAnimatedComponent`.
26602660-26612661-### What's Next?
26622662-26632663-In the next section, we'll delve into animation functions and customizing their behavior.
26642664-26652665-## React Native Reanimated: ReducedMotionConfig
26662666-26672667-**Version:** 3.x
26682668-26692669-### Overview
26702670-26712671-The `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.
26722672-26732673-> **Caution:** The new configuration will be applied globally across the entire application.
26742674-26752675-### Reference
26762676-26772677-```typescript
26782678-import { ReducedMotionConfig, ReduceMotion } from 'react-native-reanimated';
26792679-26802680-function App() {
26812681- return (
26822682- // ...
26832683- <ReducedMotionConfig mode={ReduceMotion.Never} />
26842684- // ...
26852685- );
26862686-}
26872687-```
26882688-26892689-#### Arguments
26902690-26912691-##### `mode`
26922692-26932693-This parameter determines how animations should respond to the device's reduced motion accessibility setting:
26942694-26952695-- **`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.
26962696-26972697-- **`ReduceMotion.Always`:** Consistently disables animations, regardless of the device's accessibility configuration.
26982698-26992699-- **`ReduceMotion.Never`:** Ensures that animations remain enabled at all times.
27002700-27012701-### Platform Compatibility
27022702-27032703-|Android|iOS|Web|
27042704-|-|-|-|
27052705-|✅|✅|✅|
27062706-27072707-- Reference
27082708- - Arguments
27092709-- Example
27102710-- Platform compatibility
27112711-27122712-## Accurate Call Stacks
27132713-27142714-When 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.
27152715-27162716-To 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.
27172717-27182718-### Reference
27192719-27202720-For 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.
27212721-27222722-```typescript
27232723-// metro.config.js
27242724-import { wrapWithReanimatedMetroConfig } from "react-native-reanimated/metro-config"
27252725-27262726-const config = {
27272727- // Your existing Metro configuration options
27282728-}
27292729-27302730-export default wrapWithReanimatedMetroConfig(config)
27312731-```
27322732-27332733-### Example
27342734-27352735-The 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.
27362736-27372737-|Before|After|
27382738-|-|-|
27392739-|||
27402740-27412741-### Remarks
27422742-27432743-- `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**.
27442744-27452745-|Collapsed|Expanded|
27462746-|-|-|
27472747-|||
27482748-27492749-- 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.
27502750-27512751-## Logger Configuration for Reanimated
27522752-27532753-Reanimated 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.
27542754-27552755-By default, the logger configuration requires no setup and displays all warnings and errors. To customize this behavior, use the `configureReanimatedLogger` function.
27562756-27572757-### Reference
27582758-27592759-To alter the default Reanimated logger settings, import `configureReanimatedLogger` from `react-native-reanimated` and invoke it with your desired configuration:
27602760-27612761-```typescript
27622762-import {
27632763- configureReanimatedLogger,
27642764- ReanimatedLogLevel,
27652765-} from "react-native-reanimated"
27662766-27672767-// Default configuration example
27682768-configureReanimatedLogger({
27692769- level: ReanimatedLogLevel.warn,
27702770- strict: true, // Strict mode is enabled by default
27712771-})
27722772-```
27732773-27742774-#### Configuration Options
27752775-27762776-- **`level`:** Specifies the minimum log level to display using a value from `ReanimatedLogLevel`.
27772777-27782778-- **`strict`:** A boolean that toggles strict mode. Enabling it results in additional warnings to help identify potential code issues.
27792779-27802780-### Remarks
27812781-27822782-- The logger configuration is global, affecting all Reanimated warnings and errors. It cannot be configured on a per-file or per-component basis.
27832783-27842784-- Call `configureReanimatedLogger` before creating any Reanimated animations, typically in the root file of your application.
27852785-27862786-- 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.
27872787-27882788-### Platform Compatibility
27892789-27902790-|Android|iOS|Web|
27912791-|-|-|-|
27922792-|✅|✅|✅|
27932793-27942794-```markdown
27952795-# Guides
27962796-27972797-## Worklets
27982798-27992799-Worklets are brief JavaScript functions executed on the UI thread. Reanimated utilizes worklets to compute view styles and respond to events directly on the UI thread.
28002800-28012801-## Accessibility
28022802-28032803-This section delves into how Reanimated enhances accessibility in animations, particularly through its reduced motion feature. This functionality ensures a more comfortable experience for users with motion sensitivities or those who prefer minimal movement.
28042804-28052805-## Building for Android on Windows
28062806-28072807-This article outlines basic troubleshooting steps for issues encountered when building React Native apps with Reanimated for Android devices from a Windows host machine.
28082808-28092809-## Compatibility
28102810-28112811-Currently supported React Native versions (Paper)
28122812-28132813-## Contributing
28142814-28152815-Thank you for your interest in contributing to Reanimated! Contributions, whether through triaging and commenting on issues, extending documentation, or reviewing and submitting Pull Requests, are greatly appreciated.
28162816-28172817-## Debugging Worklets
28182818-28192819-Due to Reanimated's unique architecture and its use of a secondary JS runtime, debugging worklets can be challenging.
28202820-28212821-## Migration from 1.x
28222822-28232823-We aimed to facilitate incremental migration from Reanimated 1 to Reanimated 2.
28242824-28252825-## Migration from 2.x
28262826-28272827-Reanimated 3.x introduces no breaking changes in terms of API between versions 2.x and 3.x. All code written using the Reanimated v2 API will function in 3.x without modifications. However, Reanimated 3.x completely removes support for the Reanimated v1 API. For migration guidance from 1.x to 2.x, please refer to the Migration from 1.x to 2.x guide.
28282828-28292829-## Testing with Jest
28302830-28312831-Reanimated offers a testing API based on Jest, enabling users to mock web-based animations.
28322832-28332833-## Troubleshooting
28342834-28352835-Initialization issues
28362836-28372837-## Web Support
28382838-28392839-Reanimated can be launched in a web browser. In this context, all functionalities are implemented purely in JavaScript, which may result in reduced animation efficiency.
28402840-```
28412841-28422842-```markdown
28432843-# Core (Version: 3.x)
28442844-28452845-## useSharedValue
28462846-28472847-`useSharedValue` is used for defining shared values within your components. These shared values can be utilized across different parts of the component tree.
28482848-28492849-## useAnimatedStyle
28502850-28512851-With `useAnimatedStyle`, you can create a styles object akin to StyleSheet styles, which allows animation using shared values. This enables dynamic styling changes in response to animations.
28522852-28532853-## useAnimatedProps
28542854-28552855-`useAnimatedProps` facilitates the creation of an animated props object that can be animated with shared values. It is particularly useful for animating properties of third-party components by providing them with animated props.
28562856-28572857-## useAnimatedRef
28582858-28592859-The `useAnimatedRef` function provides a reference to a view, which can then be used in conjunction with functions like measure, scrollTo, and useScrollViewOffset to manipulate the view's position or dimensions.
28602860-28612861-## useDerivedValue
28622862-28632863-`useDerivedValue` allows for the creation of new shared values derived from existing ones. This ensures that these new values remain reactive and update automatically when their dependencies change.
28642864-28652865-## createAnimatedComponent
28662866-28672867-`createAnimatedComponent` enables you to transform any React Native component into an animated version. By wrapping a component with `createAnimatedComponent`, Reanimated can animate any prop or style associated with it, enhancing the component's interactivity.
28682868-28692869-## cancelAnimation
28702870-28712871-The `cancelAnimation` function is used to stop a running animation that is linked to a shared value. This allows for greater control over animations by providing the ability to halt them when necessary.
28722872-```
28732873-28742874-```markdown
28752875-# Version 3.x: Layout Animations Overview
28762876-28772877-## Entering/Exiting Animations
28782878-28792879-These animations are designed to animate elements as they enter into or exit from the view hierarchy, providing a dynamic user experience.
28802880-28812881-## Keyframe Animations
28822882-28832883-Keyframes offer a schema for defining complex animations. They provide greater flexibility compared to standard entering and exiting presets by allowing detailed control over animation sequences.
28842884-28852885-## Layout Transitions
28862886-28872887-Layout transitions enable smooth changes during layout updates, which may involve alterations in size or position. Both aspects can be animated to enhance visual fluidity.
28882888-28892889-## Custom Animations
28902890-28912891-Custom animations offer complete control over both entering/exiting animations and layout transitions. However, they are complex and challenging to maintain. It is advisable to start with predefined presets before opting for custom solutions.
28922892-28932893-## Skipping Layout Animations
28942894-28952895-The `LayoutAnimationConfig` component allows you to bypass entering and exiting animations when needed.
28962896-28972897-## List Layout Animations
28982898-28992899-With `itemLayoutAnimation`, you can specify a layout transition for list items during layout changes. Options include using predefined transitions like `LinearTransition` or creating custom ones.
29002900-```
29012901-29022902-## Worklets
29032903-29042904-Worklets are short-running JavaScript functions that execute on the UI thread, enabling efficient style calculations and event reactions. Reanimated leverages worklets for these tasks.
29052905-29062906-### Creating Worklets
29072907-29082908-To define a custom worklet, use the `'worklet';` directive at the start of your function:
29092909-29102910-```typescript
29112911-function myWorklet() {
29122912- "worklet"
29132913- console.log("Hello from a worklet")
29142914-}
29152915-```
29162916-29172917-The 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.
29182918-29192919-### Automatic Workletization
29202920-29212921-When using Reanimated and Gesture Handler, code is typically automatically workletized and executed on the UI thread:
29222922-29232923-```typescript
29242924-import { useAnimatedStyle } from "react-native-reanimated"
29252925-29262926-function App() {
29272927- const style = useAnimatedStyle(() => {
29282928- // Executed on the UI thread
29292929- return { opacity: 0.5 }
29302930- })
29312931-}
29322932-```
29332933-29342934-### Manual Worklet Execution
29352935-29362936-To manually schedule worklet execution, use `runOnUI`:
29372937-29382938-```typescript
29392939-function myWorklet() {
29402940- "worklet"
29412941- console.log("Hello from the UI thread")
29422942-}
29432943-29442944-function onPress() {
29452945- runOnUI(myWorklet)()
29462946-}
29472947-```
29482948-29492949-Arguments can be passed to worklets as follows:
29502950-29512951-```typescript
29522952-function myWorklet(greeting: string) {
29532953- "worklet"
29542954- console.log(`${greeting} from the UI thread`)
29552955-}
29562956-29572957-function onPress() {
29582958- runOnUI(myWorklet)("Howdy")
29592959-}
29602960-```
29612961-29622962-### Worklet Closures
29632963-29642964-Worklets are closures, allowing them to access variables declared outside their scope. Only referenced variables are captured:
29652965-29662966-```typescript
29672967-const width = 135.5
29682968-29692969-function otherWorklet() {
29702970- "worklet"
29712971- console.log("Captured width is", width)
29722972-}
29732973-```
29742974-29752975-Avoid capturing large objects within worklets to prevent performance issues:
29762976-29772977-```typescript
29782978-const theme = {...}; // Large object
29792979-29802980-function myWorklet() {
29812981- 'worklet';
29822982- console.log(theme.color); // 🚨 Captures entire `theme` object
29832983-}
29842984-```
29852985-29862986-To mitigate this, assign the needed property to a separate variable:
29872987-29882988-```typescript
29892989-const theme = {...};
29902990-const color = theme.color;
29912991-29922992-function myWorklet() {
29932993- 'worklet';
29942994- console.log(color); // ✅ Captures only `color`
29952995-}
29962996-```
29972997-29982998-### Returning Data
29992999-30003000-Worklets can return data within the same thread:
30013001-30023002-```typescript
30033003-function returningWorklet() {
30043004- "worklet"
30053005- return "I'm back" // On the UI thread
30063006-}
30073007-30083008-function someWorklet() {
30093009- "worklet"
30103010- const what = returningWorklet() // Still on the UI thread
30113011- console.log("On the UI thread, other worklet says", what)
30123012-}
30133013-```
30143014-30153015-### Data Sharing Between Threads
30163016-30173017-Use shared values to pass data between the UI and JS threads:
30183018-30193019-```typescript
30203020-import { useSharedValue } from "react-native-reanimated"
30213021-30223022-function App() {
30233023- const width = useSharedValue(100)
30243024-30253025- function myWorklet() {
30263026- "worklet"
30273027- width.value += 50
30283028- }
30293029-30303030- useEffect(() => {
30313031- console.log(width.value) // Accessible on both JS and UI threads
30323032- }, [])
30333033-}
30343034-```
30353035-30363036-### Running Functions on the JS Thread
30373037-30383038-Use `runOnJS` to execute functions from the UI thread, often for non-worklet functions or React state updates:
30393039-30403040-```typescript
30413041-import { router } from "expo-router"
30423042-import { Gesture } from "react-native-gesture-handler"
30433043-30443044-function App() {
30453045- const tap = Gesture.Tap().onEnd(() => {
30463046- // Worklet context
30473047- runOnJS(router.back)()
30483048- })
30493049-}
30503050-```
30513051-30523052-Ensure functions passed to `runOnJS` are defined in the JavaScript thread scope:
30533053-30543054-```typescript
30553055-function App() {
30563056- const tap = Gesture.Tap().onEnd(() => {
30573057- // myFunction is defined on the UI thread 🚨
30583058- const myFunction = () => {}
30593059- runOnJS(myFunction)() // 💥 Error
30603060- })
30613061-}
30623062-```
30633063-30643064-### Custom Worklet Runtimes
30653065-30663066-Worklets can operate in custom runtimes beyond Reanimated's default. Libraries like VisionCamera and LiveMarkdown create their own worklet environments.
30673067-30683068-Create your own worklet runtime using `createWorkletRuntime`.
30693069-30703070-## Accessibility
30713071-30723072-This 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.
30733073-30743074-The 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:
30753075-30763076-- `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.
30773077-- `ReduceMotion.Always`: Consistently disables the animation, regardless of the device's accessibility configuration.
30783078-- `ReduceMotion.Never`: Ensures that the animation remains enabled at all times.
30793079-30803080-By default, all animations are configured with `ReduceMotion.System`.
30813081-30823082-### Reduced Motion in Animations
30833083-30843084-```typescript
30853085-import { withDelay, withTiming } from "react-native-reanimated"
30863086-30873087-function App() {
30883088- sv1.value = withTiming(0, { reduceMotion: ReduceMotion.System })
30893089- sv2.value = withDelay(
30903090- 1000,
30913091- withTiming(toValue, { duration }),
30923092- ReduceMotion.System
30933093- )
30943094- // ...
30953095-}
30963096-```
30973097-30983098-When reduced motion is enabled:
30993099-31003100-- `withSpring` and `withTiming` return the `toValue` immediately.
31013101-- `withDecay` returns the current value immediately, considering the clamp parameter.
31023102-- `withDelay` initiates the next animation immediately.
31033103-- `withRepeat`:
31043104- - If `numberOfReps` is infinite or even and the animation is reversed, then the repeated animation does not start.
31053105- - Otherwise, the repeated animation runs once.
31063106-- `withSequence` exclusively starts animations that have reduced motion disabled.
31073107-31083108-Higher-order animations pass the configuration to their children only if the children haven't been configured by the user. For example:
31093109-31103110-This animation will instantaneously reach the `toValue`:
31113111-31123112-```typescript
31133113-import { withDelay, withTiming } from "react-native-reanimated"
31143114-31153115-function App() {
31163116- sv.value = withDelay(
31173117- 1000,
31183118- withTiming(toValue, { duration }),
31193119- ReduceMotion.Always
31203120- )
31213121- // ...
31223122-}
31233123-```
31243124-31253125-This animation will execute as usual even if reduced motion is enabled on the device:
31263126-31273127-```typescript
31283128-import { withDelay, withTiming } from "react-native-reanimated"
31293129-31303130-function App() {
31313131- sv.value = withDelay(
31323132- 1000,
31333133- withTiming(toValue, { duration }),
31343134- ReduceMotion.Never
31353135- )
31363136- // ...
31373137-}
31383138-```
31393139-31403140-And here `withTiming` will be executed as usual and without delay:
31413141-31423142-```typescript
31433143-import { withDelay, withTiming } from "react-native-reanimated"
31443144-31453145-function App() {
31463146- sv.value = withDelay(
31473147- 1000,
31483148- withTiming(toValue, { duration, reduceMotion: ReduceMotion.Never }),
31493149- ReduceMotion.Always
31503150- )
31513151- // ...
31523152-}
31533153-```
31543154-31553155-### Reduced Motion in Layout Animations
31563156-31573157-```typescript
31583158-import { BounceIn } from "react-native-reanimated"
31593159-31603160-function App() {
31613161- const entering = BounceIn.reduceMotion(ReduceMotion.System)
31623162- // ...
31633163-}
31643164-```
31653165-31663166-When reduced motion is enabled:
31673167-31683168-- Entering, keyframe, and layout animations instantaneously reach their endpoints.
31693169-- Exiting animations and shared transitions are omitted.
31703170-31713171-### `useReducedMotion`
31723172-31733173-This 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.
31743174-31753175-```typescript
31763176-import { BounceIn } from "react-native-reanimated"
31773177-31783178-function App() {
31793179- const reduceMotion = useReducedMotion()
31803180- const entering = reduceMotion
31813181- ? FadeIn.reduceMotion(ReduceMotion.Never)
31823182- : BounceIn
31833183- // ...
31843184-}
31853185-```
31863186-31873187-The 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:
31883188-31893189-#### Overview
31903190-31913191-- **Library**: `react-native-reanimated`
31923192-- **Purpose**: To create smooth, performant animations on Android, iOS, and Web platforms.
31933193-- **Animations Covered**:
31943194- - Pinch
31953195- - Pinch Zoom
31963196- - Pinch Rotate
31973197- - Pinch Scale
31983198- - Pinch Translate
31993199- - Pinch X
32003200- - Pinch Y
32013201- - PinchXY
32023202- - PinchZoomRotate
32033203- - PinchZoomScale
32043204- - PinchZoomTranslate
32053205- - PinchZoomX
32063206- - PinchZoomY
32073207- - PinchZoomXY
32083208- - PinchZoomRotateScale
32093209- - PinchZoomRotateTranslate
32103210- - PinchZoomRotateX
32113211- - PinchZoomRotateY
32123212- - PinchZoomRotateXY
32133213- - PinchZoomScaleTranslate
32143214- - PinchZoomScaleX
32153215- - PinchZoomScaleY
32163216- - PinchZoomScaleXY
32173217- - PinchZoomTranslateX
32183218- - PinchZoomTranslateY
32193219- - PinchZoomTranslateXY
32203220- - PinchZoomRotateScaleTranslate
32213221- - PinchZoomRotateScaleX
32223222- - PinchZoomRotateScaleY
32233223- - PinchZoomRotateScaleXY
32243224- - PinchZoomRotateTranslateX
32253225- - PinchZoomRotateTranslateY
32263226- - PinchZoomRotateTranslateXY
32273227- - PinchZoomScaleTranslateX
32283228- - PinchZoomScaleTranslateY
32293229- - PinchZoomScaleTranslateXY
32303230- - PinchZoomRotateScaleTranslateX
32313231- - PinchZoomRotateScaleTranslateY
32323232- - PinchZoomRotateScaleTranslateXY
32333233- - Other animations like Bounce, Fade, Flip, etc.
32343234-32353235-#### Animation Configuration
32363236-32373237-##### Time-based Modifiers
32383238-32393239-- **Function**: `withTiming`
32403240-- **Customization**:
32413241- - `.easing(easingFunction: EasingFunction)`: Defines the animation curve. Default is `Easing.inOut(Easing.quad)`.
32423242- - Note: These modifiers do not affect spring animations.
32433243-32443244-##### Spring-based Modifiers
32453245-32463246-- **Function**: `withSpring`
32473247-- **Customization**:
32483248- - `.springify()`: Enables spring-based configuration.
32493249- - `.damping(value: number)`: Controls how quickly the spring stops. Default is `10`.
32503250- - `.mass(value: number)`: Represents the weight of the spring. Lower values make animations faster. Default is `1`.
32513251- - `.stiffness(value: number)`: Determines bounciness. Default is `100`.
32523252- - `.overshootClamping(value: boolean)`: Prevents bouncing over the target position. Default is `false`.
32533253- - `.restDisplacementThreshold(value: number)`: Displacement threshold for snapping to the final position without oscillations. Default is `0.001`.
32543254- - `.restSpeedThreshold(value: number)`: Speed threshold for snapping to the final position without oscillations. Default is `2`.
32553255-32563256-##### Common Modifiers
32573257-32583258-- **Customization**:
32593259- - `.duration(durationMs: number)`: Length of the animation in milliseconds. Default is `300`.
32603260- - `.delay(durationMs: number)`: Delay before starting the animation. Default is `0`.
32613261- - `.randomDelay()`: Randomizes delay between `0` and provided value, defaulting to `1000ms` if not specified.
32623262- - `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts animation based on device's reduced motion settings.
32633263- - `.withInitialValues(values: StyleProps)`: Overrides initial configuration of the animation.
32643264- - `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
32653265-32663266-#### Platform Compatibility
32673267-32683268-- **Android**: Supported
32693269-- **iOS**: Supported
32703270-- **Web**: Supported
32713271-32723272-This guide provides developers with the tools to create and customize animations effectively across multiple platforms using `react-native-reanimated`.
32733273-32743274-## Troubleshooting React Native Reanimated Build Issues on Windows
32753275-32763276-This 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:
32773277-32783278-- `Execution failed for task ':react-native-reanimated:buildCMakeDebug[x86_64]'`
32793279-- `Execution failed for task ':react-native-reanimated:buildCMakeRelWithDebInfo[arm64-v8a]'`
32803280-- `Task :react-native-reanimated:buildCMakeDebug[x86_64] FAILED`
32813281-- `C/C++: ninja: error: mkdir(...): No such file or directory`
32823282-- `C++ build system [build] failed while executing`
32833283-- `Picked up _JAVA_OPTIONS`
32843284-32853285-### What Not to Do
32863286-32873287-If you encounter any of the above errors, avoid these actions:
32883288-32893289-#### ❌ Avoid Disabling New Architecture
32903290-32913291-Starting 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.
32923292-32933293-#### ❌ Avoid Downgrading Android Gradle Plugin (AGP)
32943294-32953295-Do not modify the AGP version in `gradle.properties`. Use the version specified in the official app template to prevent version conflicts and unsupported features.
32963296-32973297-#### ❌ Avoid Downgrading Reanimated or Other Dependencies
32983298-32993299-Downgrading 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.
33003300-33013301-#### ❌ Avoid Posting Duplicate "Same Issue" Comments
33023302-33033303-Before 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.
33043304-33053305-### Recommended Actions
33063306-33073307-#### ✅ Ensure Correct Environment Setup
33083308-33093309-Follow 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.
33103310-33113311-#### ✅ Use Compatible Reanimated Version
33123312-33133313-Use the latest supported version of Reanimated based on your app setup:
33143314-33153315-- **Expo SDK**: Match major and minor versions with Expo SDK.
33163316- - Example: Expo SDK 52 supports `~3.16.x`. Update to the latest patch, e.g., `3.16.7`.
33173317-33183318-|Expo SDK Version|Reanimated Version|
33193319-|-|-|
33203320-|`52`|`~3.16.1`|
33213321-|`51`|`~3.10.1`|
33223322-|`50`|`~3.6.2`|
33233323-33243324-- **Expo Prebuild or React Native without Framework**: Use a version compatible with your React Native version according to the Compatibility table.
33253325-33263326-#### ✅ Use Appropriate CMake Version
33273327-33283328-Ensure 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`.
33293329-33303330-#### ✅ Use Appropriate Ninja Version
33313331-33323332-Use Ninja `1.12.0` or newer (latest is `1.12.1`) as older versions may not handle long paths correctly.
33333333-33343334-#### ✅ Use Compatible Android NDK Version
33353335-33363336-Match the NDK version with that used in the official app template. It should be installed automatically during app build.
33373337-33383338-#### ✅ Unset `_JAVA_OPTIONS`
33393339-33403340-Unsetting this environment variable can resolve certain errors and allow builds to pass.
33413341-33423342-#### ✅ Enable Long Paths Support in Windows Registry
33433343-33443344-Follow instructions to enable long paths support on Windows.
33453345-33463346-#### ✅ Avoid Whitespace in Project Path
33473347-33483348-Paths with spaces may cause issues. Move projects to directories without whitespace, e.g., `D:\Mobile Apps\MyAwesomeProject`.
33493349-33503350-#### ✅ Ensure Short Project Path
33513351-33523352-Avoid paths longer than 240 characters. Move or clone the project to a shorter path, e.g., `D:\AwesomeProject`.
33533353-33543354-#### ✅ Remove or Invalidate Caches
33553355-33563356-Clear compilation artifacts in directories like:
33573357-33583358-- `android\build`
33593359-- `android\.cxx`
33603360-- `android\.gradle`
33613361-- `node_modules\react-native-reanimated\android\build`
33623362-33633363-Invalidate Android Studio caches (File → Invalidate Caches…).
33643364-33653365-#### ⚠️ Persistent Issues
33663366-33673367-If problems persist after following these steps, submit an issue in the repository with full build logs and a minimal reproducible example.
33683368-33693369-## Compatibility Table
33703370-33713371-### Currently Supported React Native Versions (Paper)
33723372-33733373-|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|
33743374-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
33753375-|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
33763376-|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
33773377-|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
33783378-|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
33793379-|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
33803380-|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
33813381-|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
33823382-|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
33833383-|3.6.x – 3.8.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|
33843384-|3.5.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
33853385-|3.3.x – 3.4.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
33863386-|3.0.x – 3.2.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
33873387-|2.14.x – 2.17.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
33883388-|2.11.x – 2.13.x|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|
33893389-|2.10.x|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|
33903390-|2.5.x – 2.9.x|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|
33913391-|2.3.x – 2.4.x|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|no|
33923392-33933393-**Note:** Reanimated 2 will not receive support for the newest React Native versions. To access the latest features and updates, upgrade to Reanimated 3.
33943394-33953395-### Supported React Native Versions on the New Architecture (Fabric)
33963396-33973397-To 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.
33983398-33993399-Reanimated supports bridgeless mode.
34003400-34013401-|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|
34023402-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
34033403-|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
34043404-|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
34053405-|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
34063406-|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
34073407-|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
34083408-|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
34093409-|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
34103410-|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
34113411-|3.6.x – 3.8.x|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|no|no|
34123412-|3.1.x – 3.5.x|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|
34133413-|3.0.x|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|no|
34143414-34153415-## Animating Styles and Props
34163416-34173417-In the previous section, we explored creating simple animations, understanding shared values, and their application. In this part, we will delve into an alternative method for applying animation styles to components. We'll also examine the distinctions between animating styles versus props and how to manage them using `useAnimatedStyle` and `useAnimatedProps`.
34183418-34193419-### Animating Styles with `useAnimatedStyle`
11031103+In this section, you learned about:
3420110434213421-The `useAnimatedStyle` hook allows you to define animated styles that can be applied directly to a component's style prop. This approach is particularly useful for smoothly transitioning between different visual states.
34223422-34233423-#### Example
34243424-34253425-```typescript
34263426-import { useSharedValue, withSpring, useAnimatedStyle } from 'react-native-reanimated';
34273427-34283428-const AnimatedComponent = () => {
34293429- const opacity = useSharedValue(0);
11051105+- `Animated` components to define animatable elements.
11061106+- Shared values as the driving factor of animations using `useSharedValue`.
11071107+- Accessing and modifying shared values via their `.value` property (e.g., `sv.value = 100;`).
11081108+- Creating smooth animations by modifying shared values with functions like `withSpring`.
3430110934313431- // Define the animated styles
34323432- const animatedStyles = useAnimatedStyle(() => ({
34333433- opacity: withSpring(opacity.value),
34343434- }));
11101110+### What's Next?
3435111134363436- return <View style={[styles.view, animatedStyles]} />;
34373437-};
34383438-```
11121112+In the next section, you'll explore animating styles and props using `useAnimatedStyle` and `useAnimatedProps` hooks.
3439111334403440-### Animating Props with `useAnimatedProps`
34413441-34423442-While `useAnimatedStyle` is great for animating styles, `useAnimatedProps` allows you to animate component props. This can be useful when the animation involves more than just visual changes.
34433443-34443444-#### Example
34453445-34463446-```typescript
34473447-import { useSharedValue, withTiming, useAnimatedProps } from 'react-native-reanimated';
34483448-34493449-const AnimatedText = () => {
34503450- const fontSize = useSharedValue(14);
34513451-34523452- // Define animated props
34533453- const animatedProps = useAnimatedProps(() => ({
34543454- fontSize: withTiming(fontSize.value + 10),
34553455- }));
34563456-34573457- return <Animated.Text style={styles.text} {...animatedProps}>Hello World</Animated.Text>;
34583458-};
34593459-```
34603460-34613461-### Key Differences
34623462-34633463-- **`useAnimatedStyle`:** Best for animating styles directly. It provides a way to interpolate values and apply them as inline styles.
34643464-34653465-- **`useAnimatedProps`:** Ideal for animating props of components that do not support direct style interpolation.
34663466-34673467-By understanding these hooks, you can effectively manage animations in your React Native applications, enhancing both performance and user experience.
34683468-34693469-## useSharedValue
34703470-34713471-`useSharedValue` is a hook that allows you to define shared values within your components.
34723472-34733473-### Reference
34743474-34753475-```typescript
34763476-import { useSharedValue } from "react-native-reanimated"
34773477-34783478-function App() {
34793479- const sv = useSharedValue(100)
34803480-34813481- // Accessing the shared value
34823482- console.log(sv.value)
34833483-34843484- // Modifying the shared value
34853485- sv.value += 50
34863486-}
34873487-```
34883488-34893489-#### Arguments
34903490-34913491-##### `initialValue`
34923492-34933493-The 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`.
34943494-34953495-#### Returns
34963496-34973497-`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.
34983498-34993499-##### React Compiler Support
35003500-35013501-When 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.
35023502-35033503-```typescript
35043504-function App() {
35053505- const sv = useSharedValue(100)
35063506-35073507- const animatedStyle = useAnimatedStyle(() => {
35083508- "worklet"
35093509- return { width: sv.get() * 100 }
35103510- })
35113511-35123512- const handlePress = () => {
35133513- sv.set((value) => value + 1)
35143514- }
35153515-}
35163516-```
35173517-35183518-### Remarks
35193519-35203520-- 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.
35213521-35223522-- 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.
35233523-35243524-- 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.
35253525-35263526-- 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.
35273527-35283528-```typescript
35293529-function App() {
35303530- const sv = useSharedValue(100) // initially set to 100
35313531-35323532- sv.value += 50 // modifying the shared value
35333533-35343534- console.log(sv.value) // logs 100 due to asynchronous update on JS thread
35353535-}
35363536-```
35373537-35383538-- Avoid destructuring assignment with shared values. While valid in JavaScript, it prevents Reanimated from maintaining reactivity.
35393539-35403540-```typescript
35413541-function App() {
35423542- let { value } = sv // avoid this pattern
35433543-35443544- console.log(value) // reading is fine
35453545-35463546- value += 50 // does not update styles
35473547-}
35483548-```
35493549-35503550-- When storing objects in a shared value, ensure to reassign the entire object rather than modifying its properties individually.
35513551-35523552-```typescript
35533553-function App() {
35543554- const sv = useSharedValue({ x: 0, y: 0 })
35553555-35563556- sv.value.x = 50 // loses reactivity
35573557-35583558- sv.value = { x: 50, y: 0 } // correct approach
35593559-}
35603560-```
35613561-35623562-- For large arrays or complex objects in a shared value, use the `.modify` method to alter the existing value without creating a new one.
35633563-35643564-```typescript
35653565-function App() {
35663566- const sv = useSharedValue([1, 2, 3])
35673567-35683568- sv.value.push(1000) // loses reactivity
35693569-35703570- sv.value = [...sv.value, 1000] // creates a new copy
35713571-35723572- sv.modify((value) => {
35733573- "worklet"
35743574- value.push(1000) // correct approach
35753575- return value
35763576- })
35773577-}
35783578-```
35793579-35803580-### Platform Compatibility
35813581-35823582-|Android|iOS|Web|
35833583-|-|-|-|
35843584-|✅|✅|✅|
35853585-35863586-## Contributing Guide for Reanimated
35873587-35883588-Thank you for considering contributing to Reanimated. Contributions can range from triaging issues and enhancing documentation to reviewing Pull Requests and submitting code changes.
35893589-35903590-### Ways to Contribute
35913591-35923592-1. **Handling Open Issues**: Assist by providing detailed descriptions and reproducible examples for existing issues, which helps other contributors understand and address them more efficiently.
35933593-35943594-1. **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.
35953595-35963596-1. **Reviewing Pull Requests**: Review submitted Pull Requests to identify potential issues or bugs that may have been overlooked, ensuring high-quality contributions.
35973597-35983598-1. **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.
35993599-36003600-#### Repository Structure
36013601-36023602-The Reanimated repository is organized as follows:
36033603-36043604-```
36053605-├── apps
36063606-│ ├── common-app // Shared source for example apps
36073607-│ ├── paper-example // React Native app using Old Architecture
36083608-│ ├── fabric-example // React Native app using New Architecture
36093609-│ ├── macos-example // React Native for MacOS wrapper
36103610-│ ├── next-example // Next.js wrapper
36113611-│ ├── tvos-example // React Native for TVOS wrapper
36123612-│ └── web-example // React Native for Web wrapper
36133613-└── packages
36143614- ├── docs-reanimated // Documentation source
36153615- ├── eslint-plugin-reanimated // ESLint plugin source
36163616- └── react-native-reanimated
36173617- ├── android // Android native code
36183618- ├── apple // iOS native code
36193619- ├── Common // Shared C++ code
36203620- ├── scripts // CI pipeline scripts
36213621- ├── src // Reanimated JS source
36223622- └── plugin // Babel plugin source
36233623-```
36243624-36253625-### Handling Open Issues
36263626-36273627-Providing detailed descriptions and reproducible examples for issues can significantly aid other contributors. Ensure that issues include:
36283628-36293629-- A cloneable repository.
36303630-- Clear reproduction steps.
36313631-- Comprehensive descriptions.
36323632-- Relevant stack traces.
36333633-36343634-If these details are missing, consider asking the issue owner or providing them yourself to facilitate quicker resolutions.
36353635-36363636-### Documentation Assistance
36373637-36383638-Improving 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:
36393639-36403640-1. Clone `react-native-reanimated`.
36413641-1. Navigate to `packages/docs-reanimated`.
36423642-1. Run `yarn && yarn start` to preview changes locally.
36433643-36443644-#### Documentation Structure
36453645-36463646-Maintain a consistent structure for clarity and ease of navigation:
36473647-36483648-1. **Introduction**: Briefly describe the feature.
36493649-1. **Reference**: Provide simple usage examples with type definitions.
36503650-1. **Arguments**: Detail accepted arguments.
36513651-1. **Returns**: Explain returned values.
36523652-1. **Example**: Include videos, GIFs, or interactive demos in both light and dark modes.
36533653-1. **Remarks**: Highlight non-obvious details like platform-specific quirks.
36543654-1. **Platform Compatibility**: Specify supported platforms.
36553655-36563656-#### Writing Style Guide
36573657-36583658-- Use active voice for clarity (e.g., "The function receives the arguments").
36593659-- Write short, clear sentences to aid comprehension.
36603660-- Organize information into lists for better readability.
36613661-- Avoid acronyms unless globally recognized (e.g., UI, API).
36623662-- Use contractions for a conversational tone.
36633663-36643664-#### Embedding Interactive Examples
36653665-36663666-Use the `InteractiveExample` component with `src` and `component` props to create engaging examples. For videos:
36673667-36683668-```typescript
36693669-import AnimatedKeyboardSrc from '!!raw-loader!@site/src/examples/AnimatedKeyboard';
36703670-36713671-<InteractiveExample
36723672- src={AnimatedKeyboardSrc}
36733673- component={
36743674- <ThemedVideo
36753675- center
36763676- width={300}
36773677- sources={{
36783678- light: '/recordings/useAnimatedKeyboard_light.mov',
36793679- dark: '/recordings/useAnimatedKeyboard_dark.mov',
36803680- }}
36813681- />
36823682- }
36833683-/>;
36843684-```
36853685-36863686-For interactive components:
36873687-36883688-```typescript
36893689-import DecayTrain from '@site/src/examples/DecayTrain';
36903690-import DecayTrainSrc from '!!raw-loader!@site/src/examples/DecayTrain';
36913691-36923692-<InteractiveExample
36933693- src={DecayTrainSrc}
36943694- component={<DecayTrain />}
36953695- label="Grab and drag the train"
36963696-/>;
36973697-```
36983698-36993699-### Contributing Code
37003700-37013701-Submit Pull Requests to address issues or introduce new features. Start with "good first issue" tasks if you're new to open-source contributions.
37023702-37033703-#### Working with Android
37043704-37053705-1. Install dependencies: `yarn && yarn build`.
37063706-1. Navigate to `apps/paper-example` and run `yarn start`.
37073707-1. Open the project in Android Studio at `react-native-reanimated/apps/paper-example/android`.
37083708-37093709-#### Working with iOS
37103710-37113711-1. Install dependencies: `yarn && yarn build`.
37123712-1. Run `cd apps/paper-example/ios && bundle install && bundle exec pod install`.
37133713-1. Start Metro bundler: `cd apps/paper-example && yarn start`.
37143714-1. Open the project in Xcode at `react-native-reanimated/apps/paper-example/ios/ReanimatedExample.xcworkspace`.
37153715-37163716-#### Preparing a Pull Request
37173717-37183718-When ready, open a Pull Request using the provided template:
37193719-37203720-1. **Summary**: Link relevant issues and describe your changes.
37213721-1. **Test Plan**: Provide instructions for testing, including code from `EmptyExample` if applicable.
37223722-37233723-#### Testing Changes Locally
37243724-37253725-To test changes in your project, create a patch with `git diff` or point to a specific commit in `package.json`.
37263726-37273727-Thank you for contributing! 🎉
37283728-37293729-## Layout Transitions
11141114+## Layout transitions
3730111537311116Layout transitions enable smooth animations during layout changes, which may involve alterations in size and position. Both aspects can be animated for a seamless experience.
37321117···3988137339891374This table indicates that all predefined transitions are compatible across Android, iOS, and web platforms.
3990137539913991-## Debugging Worklets
39923992-39933993-### Overview
39943994-39953995-This 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.
39963996-39973997-#### React Native Debugging Tools
39983998-39993999-The following tools have been evaluated for compatibility with React Native apps using the Reanimated library:
40004000-40014001-- **Chrome Debugger (React Native Debugger):** Utilizes a web worker in your browser to execute app JavaScript code, supporting all available runtimes in React Native.
40024002-40034003-- **Chrome DevTools:** Connects to a remote JavaScript runtime, allowing code execution on the device. Note: Not compatible with JSC.
40044004-40054005-- **Flipper (Hermes debugger):** Facilitates using Chrome DevTools and offers additional UI inspection tools.
40064006-40074007-- **Safari DevTools:** Available only for iOS devices running JSC, similar in functionality to Chrome DevTools by connecting to a remote runtime.
40084008-40094009-- **React Developer Tools:** A standalone app for debugging UI through an inspector, monitoring performance, and profiling the application.
40104010-40114011-#### JS Context vs. UI Context
40124012-40134013-Understanding 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.
40144014-40154015-#### Debugging Web Apps
40164016-40174017-For web applications, standard browser tools or any preferred debugging tools can be used without issues when employing Reanimated on the web.
40184018-40194019-### Compatibility Summary
40204020-40214021-|Tool|Platform|JSC|Hermes|V8|
40224022-|-|-|-|-|-|
40234023-|Chrome Debugger|Android|⚛️ ✅¹|⚛️ ✅¹|⚛️ ✅¹|
40244024-||iOS|⚛️ ✅¹|⚛️ ✅¹|N/A|
40254025-|Chrome DevTools|Android|N/A|⚛️ ✅²|⚛️|
40264026-||iOS|N/A|⚛️ ✅²|N/A|
40274027-|Flipper (Hermes debugger)|Android|N/A|⚛️ ✅²|⚛️|
40284028-||iOS|N/A|⚛️ ✅²|N/A|
40294029-|Safari DevTools|Android|N/A|N/A|N/A|
40304030-||iOS|⚛️ ✅|N/A|N/A|
40314031-|React Developer Tools|Android|⚛️|⚛️|⚛️|
40324032-||iOS|⚛️|⚛️|N/A|
40334033-40344034-¹ - Functions use web implementations, running worklets on the JS thread. Measure and Layout Animations are unavailable. ² - Experimental feature.
40354035-40364036-#### Legend
40374037-40384038-- ⚛️ ✅: Special features for React Native apps using Reanimated
40394039-- ⚛️: Standard functionality with no worklet debugging available
40404040-- N/A: Not applicable in React Native apps
40414041-40424042-**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.
40434043-40444044-### Tool-Specific Details
40454045-40464046-#### Chrome Debugger
40474047-40484048-|Platform|JSC|Hermes|V8|
40494049-|-|-|-|-|
40504050-|Android|⚛️ ✅|⚛️ ✅|⚛️ ✅|
40514051-|iOS|⚛️ ✅|⚛️ ✅|N/A|
40524052-40534053-**Summary:** Functions use web implementations, running on the JS thread. Measure and Layout Animations are unavailable.
40544054-40554055-#### Chrome DevTools
40564056-40574057-|Platform|JSC|Hermes|V8|
40584058-|-|-|-|-|
40594059-|Android|N/A|⚛️ ✅²|⚛️|
40604060-|iOS|N/A|⚛️ ✅²|N/A|
40614061-40624062-**Summary:** Both contexts can be debugged. This is an experimental feature.
40634063-40644064-#### Flipper (Hermes Debugger)
40654065-40664066-|Platform|JSC|Hermes|V8|
40674067-|-|-|-|-|
40684068-|Android|N/A|⚛️ ✅²|⚛️|
40694069-|iOS|N/A|⚛️ ✅²|N/A|
40704070-40714071-**Summary:** Both contexts can be debugged. This is an experimental feature.
40724072-40734073-#### Safari DevTools
40744074-40754075-|Platform|JSC|Hermes|V8|
40764076-|-|-|-|-|
40774077-|Android|N/A|N/A|N/A|
40784078-|iOS|⚛️ ✅|N/A|N/A|
40794079-40804080-**Summary:** Available only on iOS devices with the JSC engine. Worklet debugging is supported.
40814081-40824082-#### React Developer Tools
40834083-40844084-|Platform|JSC|Hermes|V8|
40854085-|-|-|-|-|
40864086-|Android|⚛️|⚛️|⚛️|
40874087-|iOS|⚛️|⚛️|N/A|
40884088-40894089-**Summary:** Functions as expected, with profiler and layout inspector available.
40904090-40914091-#### Additional Notes
40924092-40934093-- **Console Logs:** Always appear in the primary JS runtime.
40944094-40954095-- **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.
40964096-40974097-*Efforts are ongoing to enhance debugging experiences with Chrome DevTools and Flipper on Hermes.*
40984098-40991376## Incremental Migration from Reanimated 1 to Reanimated 2
4100137741011378The 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.
···41121389- **Reanimated 1**: Use `Easing` imported from `react-native-reanimated`.
41131390- **Reanimated 2**: Replace with `EasingNode`.
4114139141154115-## Getting Started
41164116-41174117-The *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.
41184118-41194119-### What is React Native Reanimated?
13921392+## Reanimated 3.x Overview
4120139341214121-React 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.
41224122-41234123-### Quick Start
13941394+Reanimated 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.
4124139541254125-To begin a new project using Expo:
13961396+For 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."
4126139741274127-- **NPM**:
13981398+## Customizing animations
4128139941294129- ```bash
41304130- npx create-expo-app@latest my-app -e with-reanimated
41314131- ```
14001400+The 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!
4132140141334133-- **YARN**:
41344134- ```bash
41354135- yarn create expo-app my-app -e with-reanimated
41364136- ```
14021402+Reanimated 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.
4137140341384138-Alternatively, explore examples available on GitHub.
14041404+Customizing 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.
4139140541404140-### Installation
14061406+### Configuring `withTiming`
4141140741424142-Adding Reanimated to your project involves three main steps:
14081408+The `config` parameter for `withTiming` includes two properties: `duration` and `easing`.
4143140941444144-#### Step 1: Install the Package
14101410+```typescript
14111411+import { withTiming, Easing } from "react-native-reanimated"
4145141241464146-Install the `react-native-reanimated` package from npm:
14131413+withTiming(sv.value, {
14141414+ duration: 300,
14151415+ easing: Easing.inOut(Easing.quad),
14161416+})
14171417+```
4147141841484148-- **EXPO**:
14191419+The `duration` parameter specifies the time in milliseconds for the animation to reach its target value (`toValue`). By default, this is set to `300` milliseconds.
4149142041504150- ```bash
41514151- npx expo install react-native-reanimated
41524152- ```
14211421+The `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)`.
4153142241544154-- **NPM**:
14231423+To 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.
4155142441564156- ```bash
41574157- npm install react-native-reanimated
41584158- ```
14251425+### Configuring `withSpring`
4159142641604160-- **YARN**:
41614161- ```bash
41624162- yarn add react-native-reanimated
41634163- ```
14271427+Unlike `withTiming`, `withSpring` is physics-based and simulates real-world spring dynamics, making animations appear more realistic.
4164142841654165-#### Step 2: Add Reanimated's Babel Plugin
14291429+When adjusting springs, focus on these three properties: `mass`, `stiffness` (also known as *tension*), and `damping` (also known as *friction*).
4166143041674167-Include the `react-native-reanimated/plugin` in your `babel.config.js`:
14311431+```typescript
14321432+import { withSpring } from "react-native-reanimated"
4168143341694169-```javascript
41704170-module.exports = {
41714171- presets: [
41724172- // existing presets
41734173- ],
41744174- plugins: [
41754175- // other plugins,
41764176- "react-native-reanimated/plugin",
41774177- ],
41784178-}
14341434+withSpring(sv.value, {
14351435+ mass: 1,
14361436+ stiffness: 100,
14371437+ damping: 10,
14381438+})
41791439```
4180144041814181-**Caution**: Ensure that `react-native-reanimated/plugin` is the last plugin listed.
14411441+The `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.
4182144241834183-#### Step 3: Wrap Metro Config with Reanimated Wrapper (Recommended)
14431443+`Stiffness` determines the bounciness of the spring, akin to comparing a steel spring (high stiffness) with one made from soft plastic (low stiffness).
4184144441854185-Modify your `metro.config.js` to wrap the existing configuration using `wrapWithReanimatedMetroConfig`:
14451445+`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.
4186144641874187-```javascript
41884188-// metro.config.js
41894189-const {
41904190- wrapWithReanimatedMetroConfig,
41914191-} = require("react-native-reanimated/metro-config")
14471447+Reanimated includes additional properties for customizing spring animations, which you can explore in an interactive playground or through the full `withSpring` API documentation.
4192144841934193-const config = {
41944194- // Your existing Metro configuration options
41954195-}
14491449+### Summary
4196145041974197-module.exports = wrapWithReanimatedMetroConfig(config)
41984198-```
14511451+This section covered how to customize `withTiming` and `withSpring` animation functions:
4199145242004200-#### Step 4: Clear Metro Bundler Cache (Recommended)
14531453+- Both functions accept a `config` object as their second parameter.
14541454+- You can modify `withTiming` using `duration` and `easing`. Reanimated provides an `Easing` module for convenience.
14551455+- Key properties for adjusting `withSpring` include `mass`, `stiffness`, and `damping`.
4201145642024202-- **EXPO**:
14571457+### What's Next?
4203145842044204- ```bash
42054205- npx expo start -c
42064206- ```
14591459+In the next section, you'll learn about animation modifiers like `withSequence` and `withRepeat`, enabling more complex and engaging animations.
4207146042084208-- **NPM**:
14611461+## Custom animations
4209146242104210- ```bash
42114211- npm start -- --reset-cache
42124212- ```
14631463+Custom 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.
4213146442144214-- **YARN**:
42154215- ```bash
42164216- yarn start --reset-cache
42174217- ```
14651465+### Reference
4218146642194219-#### Expo Development Build
42204220-42214221-For an Expo development build, update the native code in `ios` and `android` directories by running:
42224222-42234223-```bash
42244224-npx expo prebuild
14671467+```typescript
14681468+function CustomAnimation(values: any) {
14691469+ "worklet"
14701470+ const animations = {
14711471+ // Define your animations here
14721472+ }
14731473+ const initialValues = {
14741474+ // Set initial values for animations
14751475+ }
14761476+ const callback = (finished: boolean) => {
14771477+ // Optional callback when the layout animation ends
14781478+ }
14791479+ return {
14801480+ initialValues,
14811481+ animations,
14821482+ callback,
14831483+ }
14841484+}
42251485```
4226148642274227-#### Platform-Specific Setup
14871487+### Custom Exiting Animation
4228148842294229-##### Android
14891489+#### Arguments
4230149042314231-No additional setup is required.
14911491+- `values`: Contains information about where the view was displayed and its dimensions.
14921492+ - `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
14931493+ - `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
14941494+ - `currentWidth`: View's width.
14951495+ - `currentHeight`: View's height.
14961496+ - `currentBorderRadius`: View's border radius.
14971497+ - `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
14981498+ - `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
4232149942334233-##### iOS
15001500+#### Example
4234150142354235-Before running your app on iOS, install pods with:
42364236-42374237-```bash
42384238-cd ios && pod install && cd ..
15021502+```typescript
15031503+const customExiting = (values: any) => {
15041504+ "worklet"
15051505+ const animations = {
15061506+ originX: withTiming(2 * WIDTH, { duration: 3000 }),
15071507+ opacity: withTiming(0, { duration: 2000 }),
15081508+ transform: [{ scale: withTiming(0.2, { duration: 3500 }) }],
15091509+ }
15101510+ const initialValues = {
15111511+ originX: values.currentOriginX,
15121512+ opacity: 1,
15131513+ transform: [{ scale: 1 }],
15141514+ }
15151515+ return {
15161516+ initialValues,
15171517+ animations,
15181518+ }
15191519+}
42391520```
4240152142414241-##### Web
15221522+### Custom Entering Animation
4242152342434243-For 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`:
15241524+#### Arguments
4244152542454245-- **EXPO**:
15261526+- `values`: Contains information about where the view wants to be displayed and its dimensions.
15271527+ - `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
15281528+ - `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
15291529+ - `targetWidth`: View's width.
15301530+ - `targetHeight`: View's height.
15311531+ - `targetBorderRadius`: View's border radius.
15321532+ - `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
15331533+ - `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
4246153442474247- ```bash
42484248- npx expo install @babel/plugin-proposal-export-namespace-from
42494249- ```
15351535+#### Example
4250153642514251-- **NPM**:
42524252-42534253- ```bash
42544254- npm install @babel/plugin-proposal-export-namespace-from
42554255- ```
42564256-42574257-- **YARN**:
42584258- ```bash
42594259- yarn add @babel/plugin-proposal-export-namespace-from
42604260- ```
42614261-42624262-Ensure your `babel.config.js` includes:
42634263-42644264-```javascript
42654265-module.exports = {
42664266- presets: [
42674267- // existing presets
42684268- ],
42694269- plugins: [
42704270- "@babel/plugin-proposal-export-namespace-from",
42714271- "react-native-reanimated/plugin",
42724272- ],
15371537+```typescript
15381538+const customEntering = (targetValues: any) => {
15391539+ "worklet"
15401540+ const animations = {
15411541+ originX: withTiming(targetValues.targetOriginX, { duration: 3000 }),
15421542+ opacity: withTiming(1, { duration: 2000 }),
15431543+ borderRadius: withDelay(1500, withTiming(40, { duration: 3000 })),
15441544+ transform: [
15451545+ { rotate: withTiming("0deg", { duration: 4000 }) },
15461546+ { scale: withTiming(1, { duration: 3500 }) },
15471547+ ],
15481548+ }
15491549+ const initialValues = {
15501550+ originX: -WIDTH,
15511551+ opacity: 0,
15521552+ borderRadius: 10,
15531553+ transform: [{ rotate: "90deg" }, { scale: 0.2 }],
15541554+ }
15551555+ return {
15561556+ initialValues,
15571557+ animations,
15581558+ }
42731559}
42741560```
4275156142764276-**Note**: The `react-native-reanimated/plugin` should be listed last.
15621562+### Custom Layout Transition
4277156342784278-For more advanced scenarios, such as using Reanimated with `webpack` or `Next.js`, refer to the separate Web Support guide.
15641564+#### Arguments
4279156542804280-## Reanimated 3.x Overview
15661566+- `values`: Contains before and after information about the view's origin and dimensions.
15671567+ - `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
15681568+ - `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
15691569+ - `targetWidth`: View's width.
15701570+ - `targetHeight`: View's height.
15711571+ - `targetBorderRadius`: View's border radius.
15721572+ - `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
15731573+ - `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
15741574+ - `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system (before).
15751575+ - `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system (before).
15761576+ - `currentWidth`: View's width (before).
15771577+ - `currentHeight`: View's height (before).
15781578+ - `currentBorderRadius`: View's border radius (before).
15791579+ - `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system (before).
15801580+ - `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system (before).
4281158142824282-Reanimated 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.
15821582+#### Example
4283158342844284-For 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."
15841584+```typescript
15851585+const customLayoutTransition = (values: any) => {
15861586+ "worklet"
15871587+ return {
15881588+ animations: {
15891589+ originX: withTiming(values.targetOriginX, { duration: 1000 }),
15901590+ originY: withDelay(
15911591+ 1000,
15921592+ withTiming(values.targetOriginY, { duration: 1000 })
15931593+ ),
15941594+ width: withSpring(values.targetWidth),
15951595+ height: withSpring(values.targetHeight),
15961596+ },
15971597+ initialValues: {
15981598+ originX: values.currentOriginX,
15991599+ originY: values.currentOriginY,
16001600+ width: values.currentWidth,
16011601+ height: values.currentHeight,
16021602+ },
16031603+ }
16041604+}
16051605+```
4285160642864286-```markdown
42874287-# Animations (Version: 3.x)
16071607+### Remarks
4288160842894289-## withTiming
16091609+- 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.
4290161042914291-`withTiming` allows for creating animations based on a specified duration and easing function.
16111611+### Platform Compatibility
4292161242934293-## withSpring
16131613+|Android|iOS|Web|
16141614+|-|-|-|
16151615+|✅|✅|❌|
4294161642954295-`withSpring` enables the creation of spring-based animations, providing a natural motion effect.
42964296-42974297-## withDecay
42984298-42994299-`withDecay` creates animations that simulate objects in motion experiencing friction. The animation begins at a given velocity and gradually slows down according to a specified deceleration rate until it comes to a stop.
43004300-43014301-## withSequence
43024302-43034303-`withSequence` is an animation modifier used for executing multiple animations one after another in sequence.
43044304-43054305-## withRepeat
43064306-43074307-`withRepeat` is an animation modifier that allows an animation to be repeated a certain number of times or indefinitely.
43084308-43094309-## withDelay
43104310-43114311-`withDelay` is an animation modifier that introduces a delay before starting the animation.
43124312-43134313-## withClamp
43144314-43154315-`withClamp` is an animation modifier used to restrict the movement range of an animation, ensuring it stays within predefined limits.
43164316-```
43174317-43184318-## Testing with Jest and Reanimated
16171617+## Testing with Jest
4319161843201619Reanimated 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.
43211620···44251724- [@testing-library/react-native](https://testing-library.com/docs/native-testing-library/intro)
44261725- [@testing-library/react-hooks](https://testing-library.com/docs/react-hooks-testing-library/intro) - Useful for dealing with hooks.
4427172644284428-## Custom Animations
17271727+## withTiming
4429172844304430-Custom 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.
17291729+`withTiming` enables you to create animations based on duration and easing functions.
4431173044321731### Reference
4433173244341733```typescript
44354435-function CustomAnimation(values: any) {
44364436- "worklet"
44374437- const animations = {
44384438- // Define your animations here
44394439- }
44404440- const initialValues = {
44414441- // Set initial values for animations
44424442- }
44434443- const callback = (finished: boolean) => {
44444444- // Optional callback when the layout animation ends
44454445- }
44464446- return {
44474447- initialValues,
44484448- animations,
44494449- callback,
44504450- }
17341734+import { withTiming } from "react-native-reanimated"
17351735+17361736+function App() {
17371737+ sv.value = withTiming(0)
17381738+ // ...
44511739}
44521740```
44534453-44544454-### Custom Exiting Animation
4455174144561742#### Arguments
4457174344584458-- `values`: Contains information about where the view was displayed and its dimensions.
44594459- - `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
44604460- - `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
44614461- - `currentWidth`: View's width.
44624462- - `currentHeight`: View's height.
44634463- - `currentBorderRadius`: View's border radius.
44644464- - `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
44654465- - `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
17441744+##### `toValue`
4466174544674467-#### Example
17461746+The target value for the animation. Supported categories include:
4468174744694469-```typescript
44704470-const customExiting = (values: any) => {
44714471- "worklet"
44724472- const animations = {
44734473- originX: withTiming(2 * WIDTH, { duration: 3000 }),
44744474- opacity: withTiming(0, { duration: 2000 }),
44754475- transform: [{ scale: withTiming(0.2, { duration: 3500 }) }],
44764476- }
44774477- const initialValues = {
44784478- originX: values.currentOriginX,
44794479- opacity: 1,
44804480- transform: [{ scale: 1 }],
44814481- }
44824482- return {
44834483- initialValues,
44844484- animations,
44854485- }
44864486-}
44874487-```
17481748+- **Numbers**: Can be a number or a string representation of a number.
17491749+- **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.
17501750+- **Colors**:
17511751+ - Hexadecimal integer: e.g., `0xff1234`
17521752+ - RGB: e.g., `"rgb(100, 50, 0)"`
17531753+ - RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
17541754+ - RGB Hexadecimal: e.g., `"#53575E"`
17551755+ - HSL: e.g., `"hsl(0, 50%, 50%)"`
17561756+ - Named colors: e.g., `"dodgerblue"`
17571757+- **Objects**: Objects with properties that will be animated individually.
17581758+- **Arrays**: Arrays of numbers where each value is animated separately.
17591759+- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
4488176044894489-### Custom Entering Animation
17611761+Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
4490176244914491-#### Arguments
17631763+##### `config` (Optional)
4492176444934493-- `values`: Contains information about where the view wants to be displayed and its dimensions.
44944494- - `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
44954495- - `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
44964496- - `targetWidth`: View's width.
44974497- - `targetHeight`: View's height.
44984498- - `targetBorderRadius`: View's border radius.
44994499- - `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
45004500- - `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
17651765+The configuration for timing animations. Available properties:
17661766+17671767+|Name|Type|Default|Description|
17681768+|-|-|-|-|
17691769+|duration|`number`|300|Length of the animation in milliseconds.|
17701770+|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
17711771+|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
17721772+17731773+###### `Easing`
17741774+17751775+The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
17761776+17771777+Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
4501177845024502-#### Example
17791779+Use built-in easings by passing them to the `withTiming` config:
4503178045041781```typescript
45054505-const customEntering = (targetValues: any) => {
45064506- "worklet"
45074507- const animations = {
45084508- originX: withTiming(targetValues.targetOriginX, { duration: 3000 }),
45094509- opacity: withTiming(1, { duration: 2000 }),
45104510- borderRadius: withDelay(1500, withTiming(40, { duration: 3000 })),
45114511- transform: [
45124512- { rotate: withTiming("0deg", { duration: 4000 }) },
45134513- { scale: withTiming(1, { duration: 3500 }) },
45144514- ],
45154515- }
45164516- const initialValues = {
45174517- originX: -WIDTH,
45184518- opacity: 0,
45194519- borderRadius: 10,
45204520- transform: [{ rotate: "90deg" }, { scale: 0.2 }],
45214521- }
45224522- return {
45234523- initialValues,
45244524- animations,
45254525- }
45264526-}
17821782+import { Easing } from "react-native-reanimated"
17831783+17841784+withTiming(sv.value, {
17851785+ easing: Easing.bounce,
17861786+})
45271787```
4528178845294529-### Custom Layout Transition
17891789+Available functions include:
4530179045314531-#### Arguments
17911791+- `back`: Animation where the object slightly moves back before moving forward.
17921792+- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
17931793+- `bounce`: Bouncing animation.
17941794+- `circle`: Circular function.
17951795+- `cubic`: Cubic function.
17961796+- `ease`: Simple inertial animation.
17971797+- `elastic(bounciness?: number)`: Spring interaction.
17981798+- `exp`: Exponential function.
17991799+- `linear`: Linear function.
18001800+- `poly(n: number)`: Higher power functions like quartic, quintic.
18011801+- `quad`: Quadratic function.
18021802+- `sin`: Sinusoidal function.
18031803+18041804+Helpers to modify easing functions:
18051805+18061806+- `in(easing: EasingFunction)`: Runs an easing function forwards.
18071807+- `inOut(easing: EasingFunction)`: Symmetrical easing function.
18081808+- `out(easing: EasingFunction)`: Runs an easing function backwards.
18091809+18101810+##### `callback` (Optional)
18111811+18121812+A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
4532181345334533-- `values`: Contains before and after information about the view's origin and dimensions.
45344534- - `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
45354535- - `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
45364536- - `targetWidth`: View's width.
45374537- - `targetHeight`: View's height.
45384538- - `targetBorderRadius`: View's border radius.
45394539- - `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
45404540- - `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
45414541- - `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system (before).
45424542- - `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system (before).
45434543- - `currentWidth`: View's width (before).
45444544- - `currentHeight`: View's height (before).
45454545- - `currentBorderRadius`: View's border radius (before).
45464546- - `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system (before).
45474547- - `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system (before).
18141814+#### Returns
4548181545494549-#### Example
18161816+`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`.
4550181745514551-```typescript
45524552-const customLayoutTransition = (values: any) => {
45534553- "worklet"
45544554- return {
45554555- animations: {
45564556- originX: withTiming(values.targetOriginX, { duration: 1000 }),
45574557- originY: withDelay(
45584558- 1000,
45594559- withTiming(values.targetOriginY, { duration: 1000 })
45604560- ),
45614561- width: withSpring(values.targetWidth),
45624562- height: withSpring(values.targetHeight),
45634563- },
45644564- initialValues: {
45654565- originX: values.currentOriginX,
45664566- originY: values.currentOriginY,
45674567- width: values.currentWidth,
45684568- height: values.currentHeight,
45694569- },
45704570- }
45714571-}
45724572-```
18181818+### Example
4573181945741820### Remarks
4575182145764576-- 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.
18221822+- The callback passed as the third argument is automatically workletized and executed on the UI thread.
4577182345781824### Platform Compatibility
4579182545801826|Android|iOS|Web|
45811827|-|-|-|
45824582-|✅|✅|❌|
18281828+|✅|✅|✅|
4583182945841830## useAnimatedProps
45851831···49392185import "raf/polyfill"
49402186```
4941218749424942-```markdown
49434943-## About
49444944-49454945-### What is Reanimated Babel Plugin?
49464946-49474947-The Reanimated Babel Plugin is a tool designed to enhance the performance of animations in React Native applications. It works by transforming animation code during the build process, allowing for more efficient execution on mobile devices. By leveraging this plugin, developers can create smooth and responsive animations that run directly on the UI thread, bypassing JavaScript's limitations.
49484948-```
49494949-49502188## React Native Reanimated: List Layout Animations (Version 3.x)
4951218949522190### Overview
···50272265- **Remarks**
50282266- **Platform compatibility**
5029226750305030-## withTiming
50315031-50325032-`withTiming` enables you to create animations based on duration and easing functions.
50335033-50345034-### Reference
50355035-50365036-```typescript
50375037-import { withTiming } from "react-native-reanimated"
50385038-50395039-function App() {
50405040- sv.value = withTiming(0)
50415041- // ...
50425042-}
50435043-```
50445044-50455045-#### Arguments
50465046-50475047-##### `toValue`
50485048-50495049-The target value for the animation. Supported categories include:
50505050-50515051-- **Numbers**: Can be a number or a string representation of a number.
50525052-- **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.
50535053-- **Colors**:
50545054- - Hexadecimal integer: e.g., `0xff1234`
50555055- - RGB: e.g., `"rgb(100, 50, 0)"`
50565056- - RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
50575057- - RGB Hexadecimal: e.g., `"#53575E"`
50585058- - HSL: e.g., `"hsl(0, 50%, 50%)"`
50595059- - Named colors: e.g., `"dodgerblue"`
50605060-- **Objects**: Objects with properties that will be animated individually.
50615061-- **Arrays**: Arrays of numbers where each value is animated separately.
50625062-- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
50635063-50645064-Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
50655065-50665066-##### `config` (Optional)
50675067-50685068-The configuration for timing animations. Available properties:
50695069-50705070-|Name|Type|Default|Description|
50715071-|-|-|-|-|
50725072-|duration|`number`|300|Length of the animation in milliseconds.|
50735073-|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
50745074-|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
50755075-50765076-###### `Easing`
50775077-50785078-The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
50795079-50805080-Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
50815081-50825082-Use built-in easings by passing them to the `withTiming` config:
50835083-50845084-```typescript
50855085-import { Easing } from "react-native-reanimated"
50865086-50875087-withTiming(sv.value, {
50885088- easing: Easing.bounce,
50895089-})
50905090-```
50915091-50925092-Available functions include:
50935093-50945094-- `back`: Animation where the object slightly moves back before moving forward.
50955095-- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
50965096-- `bounce`: Bouncing animation.
50975097-- `circle`: Circular function.
50985098-- `cubic`: Cubic function.
50995099-- `ease`: Simple inertial animation.
51005100-- `elastic(bounciness?: number)`: Spring interaction.
51015101-- `exp`: Exponential function.
51025102-- `linear`: Linear function.
51035103-- `poly(n: number)`: Higher power functions like quartic, quintic.
51045104-- `quad`: Quadratic function.
51055105-- `sin`: Sinusoidal function.
51065106-51075107-Helpers to modify easing functions:
51085108-51095109-- `in(easing: EasingFunction)`: Runs an easing function forwards.
51105110-- `inOut(easing: EasingFunction)`: Symmetrical easing function.
51115111-- `out(easing: EasingFunction)`: Runs an easing function backwards.
51125112-51135113-##### `callback` (Optional)
51145114-51155115-A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
51165116-51175117-#### Returns
51185118-51195119-`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`.
51205120-51215121-### Example
51225122-51235123-### Remarks
51245124-51255125-- The callback passed as the third argument is automatically workletized and executed on the UI thread.
51265126-51275127-### Platform Compatibility
51285128-51295129-|Android|iOS|Web|
51305130-|-|-|-|
51315131-|✅|✅|✅|
51325132-51335133-## Getting Started
22682268+## Getting started
5134226951352270The *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.
51362271···53442479|-|-|-|
53452480|✅|✅|✅|
5346248153475347-```markdown
53485348-# Overview
24822482+## Getting started
24832483+24842484+The *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.
24852485+24862486+### What is React Native Reanimated?
24872487+24882488+React 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.
24892489+24902490+### Quick Start
24912491+24922492+To begin a new project using Expo:
24932493+24942494+- **NPM**:
24952495+24962496+ ```bash
24972497+ npx create-expo-app@latest my-app -e with-reanimated
24982498+ ```
5349249953505350-The Shared Element Transition feature is currently in the experimental stage and should not be used in production environments at this time. Feedback from users is being sought to enhance its development and implementation.
25002500+- **YARN**:
25012501+ ```bash
25022502+ yarn create expo-app my-app -e with-reanimated
25032503+ ```
5351250453525352-## Key Points
25052505+Alternatively, explore examples available on GitHub.
5353250653545354-- **Experimental Status**: The feature is still under development and testing.
53555355-- **Not for Production Use**: It's advised against using it in live applications until further notice.
53565356-- **Feedback Requested**: User input is crucial for refining the feature.
25072507+### Installation
25082508+25092509+Adding Reanimated to your project involves three main steps:
25102510+25112511+#### Step 1: Install the Package
25122512+25132513+Install the `react-native-reanimated` package from npm:
25142514+25152515+- **EXPO**:
25162516+25172517+ ```bash
25182518+ npx expo install react-native-reanimated
25192519+ ```
25202520+25212521+- **NPM**:
25222522+25232523+ ```bash
25242524+ npm install react-native-reanimated
25252525+ ```
25262526+25272527+- **YARN**:
25282528+ ```bash
25292529+ yarn add react-native-reanimated
25302530+ ```
25312531+25322532+#### Step 2: Add Reanimated's Babel Plugin
25332533+25342534+Include the `react-native-reanimated/plugin` in your `babel.config.js`:
25352535+25362536+```javascript
25372537+module.exports = {
25382538+ presets: [
25392539+ // existing presets
25402540+ ],
25412541+ plugins: [
25422542+ // other plugins,
25432543+ "react-native-reanimated/plugin",
25442544+ ],
25452545+}
53572546```
5358254753595359-## Customizing Animations
25482548+**Caution**: Ensure that `react-native-reanimated/plugin` is the last plugin listed.
5360254953615361-The 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!
25502550+#### Step 3: Wrap Metro Config with Reanimated Wrapper (Recommended)
5362255153635363-Reanimated 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.
25522552+Modify your `metro.config.js` to wrap the existing configuration using `wrapWithReanimatedMetroConfig`:
5364255353655365-Customizing 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.
25542554+```javascript
25552555+// metro.config.js
25562556+const {
25572557+ wrapWithReanimatedMetroConfig,
25582558+} = require("react-native-reanimated/metro-config")
5366255953675367-### Configuring `withTiming`
25602560+const config = {
25612561+ // Your existing Metro configuration options
25622562+}
5368256353695369-The `config` parameter for `withTiming` includes two properties: `duration` and `easing`.
25642564+module.exports = wrapWithReanimatedMetroConfig(config)
25652565+```
5370256653715371-```typescript
53725372-import { withTiming, Easing } from "react-native-reanimated"
25672567+#### Step 4: Clear Metro Bundler Cache (Recommended)
25682568+25692569+- **EXPO**:
25702570+25712571+ ```bash
25722572+ npx expo start -c
25732573+ ```
25742574+25752575+- **NPM**:
25762576+25772577+ ```bash
25782578+ npm start -- --reset-cache
25792579+ ```
25802580+25812581+- **YARN**:
25822582+ ```bash
25832583+ yarn start --reset-cache
25842584+ ```
5373258553745374-withTiming(sv.value, {
53755375- duration: 300,
53765376- easing: Easing.inOut(Easing.quad),
53775377-})
25862586+#### Expo Development Build
25872587+25882588+For an Expo development build, update the native code in `ios` and `android` directories by running:
25892589+25902590+```bash
25912591+npx expo prebuild
53782592```
5379259353805380-The `duration` parameter specifies the time in milliseconds for the animation to reach its target value (`toValue`). By default, this is set to `300` milliseconds.
25942594+#### Platform-Specific Setup
5381259553825382-The `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)`.
25962596+##### Android
5383259753845384-To 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.
25982598+No additional setup is required.
5385259953865386-### Configuring `withSpring`
26002600+##### iOS
5387260153885388-Unlike `withTiming`, `withSpring` is physics-based and simulates real-world spring dynamics, making animations appear more realistic.
26022602+Before running your app on iOS, install pods with:
5389260353905390-When adjusting springs, focus on these three properties: `mass`, `stiffness` (also known as *tension*), and `damping` (also known as *friction*).
26042604+```bash
26052605+cd ios && pod install && cd ..
26062606+```
5391260753925392-```typescript
53935393-import { withSpring } from "react-native-reanimated"
26082608+##### Web
5394260953955395-withSpring(sv.value, {
53965396- mass: 1,
53975397- stiffness: 100,
53985398- damping: 10,
53995399-})
54005400-```
26102610+For 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`:
5401261154025402-The `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.
26122612+- **EXPO**:
5403261354045404-`Stiffness` determines the bounciness of the spring, akin to comparing a steel spring (high stiffness) with one made from soft plastic (low stiffness).
26142614+ ```bash
26152615+ npx expo install @babel/plugin-proposal-export-namespace-from
26162616+ ```
5405261754065406-`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.
26182618+- **NPM**:
5407261954085408-Reanimated includes additional properties for customizing spring animations, which you can explore in an interactive playground or through the full `withSpring` API documentation.
26202620+ ```bash
26212621+ npm install @babel/plugin-proposal-export-namespace-from
26222622+ ```
5409262354105410-### Summary
26242624+- **YARN**:
26252625+ ```bash
26262626+ yarn add @babel/plugin-proposal-export-namespace-from
26272627+ ```
5411262854125412-This section covered how to customize `withTiming` and `withSpring` animation functions:
26292629+Ensure your `babel.config.js` includes:
5413263054145414-- Both functions accept a `config` object as their second parameter.
54155415-- You can modify `withTiming` using `duration` and `easing`. Reanimated provides an `Easing` module for convenience.
54165416-- Key properties for adjusting `withSpring` include `mass`, `stiffness`, and `damping`.
26312631+```javascript
26322632+module.exports = {
26332633+ presets: [
26342634+ // existing presets
26352635+ ],
26362636+ plugins: [
26372637+ "@babel/plugin-proposal-export-namespace-from",
26382638+ "react-native-reanimated/plugin",
26392639+ ],
26402640+}
26412641+```
5417264254185418-### What's Next?
26432643+**Note**: The `react-native-reanimated/plugin` should be listed last.
5419264454205420-In the next section, you'll learn about animation modifiers like `withSequence` and `withRepeat`, enabling more complex and engaging animations.
26452645+For more advanced scenarios, such as using Reanimated with `webpack` or `Next.js`, refer to the separate Web Support guide.
5421264654222647## withSpring
54232648···55922817|-|-|-|
55932818|✅|✅|✅|
5594281955955595-## createWorkletRuntime
28202820+## Web Support
28212821+28222822+Reanimated 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.
28232823+28242824+### Step 1: Install the Package
28252825+28262826+Install `@babel/plugin-proposal-export-namespace-from` using one of the following package managers:
28272827+28282828+- **EXPO**
28292829+28302830+ ```bash
28312831+ npx expo install @babel/plugin-proposal-export-namespace-from
28322832+ ```
28332833+28342834+- **NPM**
5596283555975597-The `createWorkletRuntime` function is designed to establish a new JavaScript runtime environment specifically for executing worklets, potentially on threads distinct from those used by standard JavaScript or the UI. This functionality is primarily intended for use by third-party libraries that require integration with worklets.
28362836+ ```bash
28372837+ npm install @babel/plugin-proposal-export-namespace-from
28382838+ ```
5598283955995599-Upon invocation, `createWorkletRuntime` returns an object representing the newly created runtime. This object must be communicated to the C++ side via the JavaScript Interface (JSI) to facilitate subsequent operations and interactions within the worklet environment.
28402840+- **YARN**
28412841+ ```bash
28422842+ yarn add @babel/plugin-proposal-export-namespace-from
28432843+ ```
5600284456015601-## Animating Styles and Props
28452845+### Step 2: Add Plugins to Config File
28462846+28472847+Update your `babel.config.js` by adding the following plugins:
28482848+28492849+```javascript
28502850+module.exports = {
28512851+ presets: [
28522852+ // Existing presets...
28532853+ ],
28542854+ plugins: [
28552855+ ...,
28562856+ '@babel/plugin-proposal-export-namespace-from',
28572857+ 'react-native-reanimated/plugin', // Ensure this is listed last
28582858+ ],
28592859+};
28602860+```
28612861+28622862+**Caution:** Make sure `react-native-reanimated/plugin` is the last plugin in the list.
28632863+28642864+### Step 3: Launch Your App
28652865+28662866+To start a playground app in the browser, use:
28672867+28682868+```bash
28692869+yarn web
28702870+```
28712871+28722872+For example applications from the Reanimated repository, execute these commands at the root of the repository:
28732873+28742874+```bash
28752875+yarn && yarn build
28762876+```
28772877+28782878+Then navigate to `apps/web-example` and run:
28792879+28802880+```bash
28812881+yarn start
28822882+```
28832883+28842884+### Webpack Support
28852885+28862886+To use Reanimated in a Webpack app, adjust your configuration as follows:
28872887+28882888+Example Webpack config with Reanimated support:
28892889+28902890+```javascript
28912891+const HtmlWebpackPlugin = require("html-webpack-plugin")
28922892+const webpack = require("webpack")
28932893+28942894+module.exports = {
28952895+ entry: ["babel-polyfill", "./index.js"],
28962896+ plugins: [
28972897+ new HtmlWebpackPlugin({
28982898+ filename: "index.html",
28992899+ template: "./index.html",
29002900+ }),
29012901+ new webpack.EnvironmentPlugin({ JEST_WORKER_ID: null }),
29022902+ new webpack.DefinePlugin({ process: { env: {} } }),
29032903+ ],
29042904+ module: {
29052905+ rules: [
29062906+ {
29072907+ test: /\.(js|jsx)$/,
29082908+ use: {
29092909+ loader: "babel-loader",
29102910+ options: {
29112911+ presets: [
29122912+ "@babel/preset-react",
29132913+ { plugins: ["@babel/plugin-proposal-class-properties"] },
29142914+ ],
29152915+ },
29162916+ },
29172917+ },
29182918+ ],
29192919+ },
29202920+ resolve: {
29212921+ alias: { "react-native$": "react-native-web" },
29222922+ extensions: [".web.js", ".js"],
29232923+ },
29242924+}
29252925+```
29262926+29272927+### Web Without the Babel Plugin
29282928+29292929+Reanimated can be used without its Babel plugin by manually passing dependency arrays to hooks. This approach is valid for both web and native platforms.
29302930+29312931+Ensure these hooks include a dependency array as their last argument:
29322932+29332933+- `useDerivedValue`
29342934+- `useAnimatedStyle`
29352935+- `useAnimatedProps`
29362936+- `useAnimatedReaction`
29372937+29382938+Example usage:
29392939+29402940+```javascript
29412941+const sv = useSharedValue(0)
29422942+const dv = useDerivedValue(
29432943+ () => sv.value + 1,
29442944+ [sv] // dependency array here
29452945+)
29462946+```
29472947+29482948+**Caution:** Pass the root dependency (`sv`) rather than `sv.value`.
29492949+29502950+Babel users must still install the `@babel/plugin-proposal-class-properties` plugin.
29512951+29522952+#### ESLint Support
29532953+29542954+To add ESLint support for Reanimated hooks, update your ESLint configuration:
29552955+29562956+```json
29572957+{
29582958+ "rules": {
29592959+ "react-hooks/exhaustive-deps": [
29602960+ "error",
29612961+ {
29622962+ "additionalHooks": "(useAnimatedStyle|useDerivedValue|useAnimatedProps)"
29632963+ }
29642964+ ]
29652965+ }
29662966+}
29672967+```
29682968+29692969+**Info:** This assumes the `react-hooks` ESLint plugin is installed.
29702970+29712971+If using ESLint autofix, manually correct any `.value` additions to dependency arrays:
29722972+29732973+```javascript
29742974+const sv = useSharedValue(0)
29752975+29762976+// 🚨 bad: sv.value in array
29772977+const dv = useDerivedValue(() => sv.value, [sv.value])
29782978+29792979+// ✅ good: sv in array
29802980+const dv = useDerivedValue(() => sv.value, [sv])
29812981+```
29822982+29832983+### Solito / Next.js Compatibility
29842984+29852985+An experimental SWC plugin is being developed. Until then, follow the "Web without a Babel Plugin" instructions.
29862986+29872987+#### Next.js Polyfill
29882988+29892989+To use Reanimated with Next.js/Solito, add the `raf` polyfill for `requestAnimationFrame`:
29902990+29912991+```bash
29922992+yarn add raf
29932993+```
29942994+29952995+Include this at the top of your `_app.tsx`:
29962996+29972997+```javascript
29982998+import "raf/polyfill"
29992999+```
30003000+30013001+## runOnJS
30023002+30033003+The `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.
30043004+30053005+`runOnJS` is commonly used to update React state either after an animation completes or conditionally within a gesture interaction.
30063006+30073007+### Reference
30083008+30093009+```typescript
30103010+import { runOnJS } from "react-native-reanimated"
30113011+30123012+function App() {
30133013+ // Executing on the UI thread
30143014+ runOnJS(navigation.goBack)()
30153015+}
30163016+```
30173017+30183018+#### Arguments
30193019+30203020+##### `fn`
30213021+30223022+A 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);`.
30233023+30243024+#### Returns
30253025+30263026+`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.
30273027+30283028+**Note:** Ensure you call the function returned from `runOnJS`.
30293029+30303030+### Example
30313031+30323032+### Remarks
30333033+30343034+- 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:
30353035+30363036+ ```typescript
30373037+ withTiming(0, {}, () => {
30383038+ // myFunction is defined on the UI thread 🚨
30393039+ const myFunction = () => {
30403040+ // ...
30413041+ }
30423042+ runOnJS(myFunction)() // 💥
30433043+ })
30443044+ ```
30453045+30463046+- A common mistake is to execute a function inside `runOnJS` like this: ~~`runOnJS(setValue(10))()`~~. The correct usage would be `runOnJS(setValue)(10)`.
30473047+30483048+- It's safe to run functions via `runOnJS` on the JavaScript thread, as it has no adverse effects.
30493049+30503050+### Platform Compatibility
30513051+30523052+|Android|iOS|Web|
30533053+|-|-|-|
30543054+|✅|✅|✅|
30553055+30563056+## withTiming
30573057+30583058+`withTiming` enables you to create animations based on duration and easing functions.
30593059+30603060+### Reference
30613061+30623062+```typescript
30633063+import { withTiming } from "react-native-reanimated"
30643064+30653065+function App() {
30663066+ sv.value = withTiming(0)
30673067+ // ...
30683068+}
30693069+```
30703070+30713071+#### Arguments
30723072+30733073+##### `toValue`
30743074+30753075+The target value for the animation. Supported categories include:
30763076+30773077+- **Numbers**: Can be a number or a string representation of a number.
30783078+- **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.
30793079+- **Colors**:
30803080+ - Hexadecimal integer: e.g., `0xff1234`
30813081+ - RGB: e.g., `"rgb(100, 50, 0)"`
30823082+ - RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
30833083+ - RGB Hexadecimal: e.g., `"#53575E"`
30843084+ - HSL: e.g., `"hsl(0, 50%, 50%)"`
30853085+ - Named colors: e.g., `"dodgerblue"`
30863086+- **Objects**: Objects with properties that will be animated individually.
30873087+- **Arrays**: Arrays of numbers where each value is animated separately.
30883088+- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
30893089+30903090+Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
30913091+30923092+##### `config` (Optional)
30933093+30943094+The configuration for timing animations. Available properties:
30953095+30963096+|Name|Type|Default|Description|
30973097+|-|-|-|-|
30983098+|duration|`number`|300|Length of the animation in milliseconds.|
30993099+|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
31003100+|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
31013101+31023102+###### `Easing`
31033103+31043104+The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
31053105+31063106+Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
31073107+31083108+Use built-in easings by passing them to the `withTiming` config:
31093109+31103110+```typescript
31113111+import { Easing } from "react-native-reanimated"
31123112+31133113+withTiming(sv.value, {
31143114+ easing: Easing.bounce,
31153115+})
31163116+```
31173117+31183118+Available functions include:
31193119+31203120+- `back`: Animation where the object slightly moves back before moving forward.
31213121+- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
31223122+- `bounce`: Bouncing animation.
31233123+- `circle`: Circular function.
31243124+- `cubic`: Cubic function.
31253125+- `ease`: Simple inertial animation.
31263126+- `elastic(bounciness?: number)`: Spring interaction.
31273127+- `exp`: Exponential function.
31283128+- `linear`: Linear function.
31293129+- `poly(n: number)`: Higher power functions like quartic, quintic.
31303130+- `quad`: Quadratic function.
31313131+- `sin`: Sinusoidal function.
31323132+31333133+Helpers to modify easing functions:
31343134+31353135+- `in(easing: EasingFunction)`: Runs an easing function forwards.
31363136+- `inOut(easing: EasingFunction)`: Symmetrical easing function.
31373137+- `out(easing: EasingFunction)`: Runs an easing function backwards.
31383138+31393139+##### `callback` (Optional)
31403140+31413141+A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
31423142+31433143+#### Returns
31443144+31453145+`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`.
31463146+31473147+### Example
31483148+31493149+### Remarks
31503150+31513151+- The callback passed as the third argument is automatically workletized and executed on the UI thread.
31523152+31533153+### Platform Compatibility
31543154+31553155+|Android|iOS|Web|
31563156+|-|-|-|
31573157+|✅|✅|✅|
31583158+31593159+## Animating styles and props
5602316056033161In this section, we explore different methods for passing animation styles to components. We will differentiate between animating styles and props using `useAnimatedStyle` and `useAnimatedProps`.
56043162···57943352|-|-|-|
57953353|✅|✅|✅|
5796335457975797-## Run On JS
57985798-57995799-The `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.
33553355+## runOnUI
5800335658015801-`runOnJS` is commonly used to update React state either after an animation completes or conditionally within a gesture interaction.
33573357+The `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.
5802335858033359### Reference
5804336058053361```typescript
58065806-import { runOnJS } from "react-native-reanimated"
33623362+import { runOnUI } from "react-native-reanimated"
5807336358083364function App() {
58095809- // Executing on the UI thread
58105810- runOnJS(navigation.goBack)()
33653365+ // Example usage in an event handler or effect
33663366+ runOnUI((greeting: string) => {
33673367+ console.log(`${greeting} from the UI thread`)
33683368+ })("Howdy")
33693369+33703370+ // ...
58113371}
58123372```
5813337358143374#### Arguments
5815337558165816-##### `fn`
33763376+##### fn
5817337758185818-A 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);`.
33783378+A 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)`.
5819337958203380#### Returns
5821338158225822-`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.
33823382+`runOnUI` returns a function that accepts arguments for the initially provided function.
5823338358245824-**Note:** Ensure you call the function returned from `runOnJS`.
33843384+**Note:** Ensure you invoke the function returned from `runOnUI`.
5825338558263386### Example
5827338758283388### Remarks
5829338958305830-- 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:
33903390+- 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.
5831339158325832- ```typescript
58335833- withTiming(0, {}, () => {
58345834- // myFunction is defined on the UI thread 🚨
58355835- const myFunction = () => {
58365836- // ...
58375837- }
58385838- runOnJS(myFunction)() // 💥
58395839- })
58405840- ```
33923392+- 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)`.
5841339358425842-- A common mistake is to execute a function inside `runOnJS` like this: ~~`runOnJS(setValue(10))()`~~. The correct usage would be `runOnJS(setValue)(10)`.
33943394+- The callback provided as an argument is automatically workletized, making it ready for execution on the UI thread.
5843339558445844-- It's safe to run functions via `runOnJS` on the JavaScript thread, as it has no adverse effects.
33963396+- Avoid executing `runOnUI` directly on the UI thread to prevent errors.
5845339758463398### Platform Compatibility
58473399···58493401|-|-|-|
58503402|✅|✅|✅|
5851340358525852-## runOnUI
34043404+## runOnRuntime
5853340558545854-The `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.
34063406+The `runOnRuntime` function allows you to execute workletized functions asynchronously on a separate worklet runtime, which operates on a different thread.
5855340758563408### Reference
5857340958583410```typescript
58595859-import { runOnUI } from "react-native-reanimated"
34113411+import { createWorkletRuntime, runOnRuntime } from "react-native-reanimated"
34123412+34133413+const workletRuntime = createWorkletRuntime("background")
5860341458613415function App() {
58623416 // Example usage in an event handler or effect
58635863- runOnUI((greeting: string) => {
58645864- console.log(`${greeting} from the UI thread`)
34173417+ runOnRuntime(workletRuntime, (greeting) => {
34183418+ console.log(`${greeting} from a separate thread`)
58653419 })("Howdy")
5866342058673421 // ...
···58693423```
5870342458713425#### Arguments
34263426+34273427+##### workletRuntime
34283428+34293429+A reference to the worklet runtime created using `createWorkletRuntime`.
5872343058733431##### fn
5874343258755875-A 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)`.
34333433+A 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)`.
5876343458773435#### Returns
5878343658795879-`runOnUI` returns a function that accepts arguments for the initially provided function.
58805880-58815881-**Note:** Ensure you invoke the function returned from `runOnUI`.
34373437+`runOnRuntime` returns a function that accepts arguments for the function provided as its first argument.
5882343858835883-### Example
34393439+**Note:** Ensure you call the function returned from `runOnRuntime`.
5884344058853441### Remarks
5886344258875887-- 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.
34433443+- A common mistake is to execute a function inside of `runOnRuntime` incorrectly, such as: ~~`runOnRuntime(myWorklet(10))()`~~. The correct usage is `runOnRuntime(myWorklet)(10)`.
5888344458895889-- 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)`.
34453445+- 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.
5890344658915891-- The callback provided as an argument is automatically workletized, making it ready for execution on the UI thread.
34473447+- `runOnRuntime` can be called on any runtime, including the RN runtime, UI runtime, and other worklet runtimes.
5892344858935893-- Avoid executing `runOnUI` directly on the UI thread to prevent errors.
34493449+- 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.
5894345058953451### Platform Compatibility
5896345258973453|Android|iOS|Web|
58983454|-|-|-|
58995899-|✅|✅|✅|
34553455+|✅|✅|❌|
5900345659015901-## Your First Animation
34573457+## Applying modifiers
5902345859035903-This 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.
34593459+Reanimated provides built-in modifiers for customizing animations: `withRepeat`, `withSequence`, and `withDelay`. This guide demonstrates how to use these modifiers by creating a shake animation.
5904346059055905-### Using an Animated Component
34613461+### Starting Point
5906346259075907-To start animating components in React Native using Reanimated, import the `Animated` object:
34633463+We'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.
5908346459093465```typescript
59105910-import Animated from "react-native-reanimated"
59115911-```
34663466+export default function App() {
34673467+ const offset = useSharedValue<number>(0);
5912346859135913-The `Animated` object wraps native components like `View`, `ScrollView`, or `FlatList`. Use these components as you would any other JSX component:
34693469+ const style = useAnimatedStyle(() => ({
34703470+ transform: [{ translateX: offset.value }],
34713471+ }));
5914347259155915-```typescript
59165916-import Animated from 'react-native-reanimated';
34733473+ const OFFSET = 40;
5917347459185918-export default function App() {
34753475+ const handlePress = () => {
34763476+ offset.value = withTiming(OFFSET);
34773477+ };
34783478+59193479 return (
59205920- <Animated.View
59215921- style={{
59225922- width: 100,
59235923- height: 100,
59245924- backgroundColor: 'violet',
59255925- }}
59265926- />
34803480+ <View style={styles.container}>
34813481+ <Animated.View style={[styles.box, style]} />
34823482+ <Button title="shake" onPress={handlePress} />
34833483+ </View>
59273484 );
59283485}
59293486```
5930348759315931-### Defining a Shared Value
34883488+### Repeating an Animation
5932348959335933-Shared values are essential for animations, acting like React state synchronized between JavaScript and the native side. Create shared values using `useSharedValue`:
34903490+To create a shake effect, use the `withRepeat` modifier. This allows you to repeat an animation multiple times or indefinitely.
5934349159353492```typescript
59365936-import { useSharedValue } from "react-native-reanimated"
34933493+import { withRepeat } from "react-native-reanimated"
34943494+34953495+function App() {
34963496+ sv.value = withRepeat(withTiming(50), 5)
34973497+}
59373498```
5938349959395939-Define shared values within your component's body to store any JS value or data structure.
35003500+Pass a number for repetitions or a non-positive value for infinite repetition. Use `true` as the third argument to reverse the animation direction.
5940350159415941-For example, set a default value of `100` for width in an `Animated.View`:
35023502+Updated example:
5942350359433504```typescript
59445944-import Animated, { useSharedValue } from 'react-native-reanimated';
35053505+export default function App() {
35063506+ const offset = useSharedValue<number>(0);
35073507+35083508+ const style = useAnimatedStyle(() => ({
35093509+ transform: [{ translateX: offset.value }],
35103510+ }));
35113511+35123512+ const OFFSET = 40;
5945351359465946-export default function App() {
59475947- const width = useSharedValue(100);
35143514+ const handlePress = () => {
35153515+ offset.value = withRepeat(withTiming(OFFSET), 5, true);
35163516+ };
5948351759493518 return (
59505950- <Animated.View
59515951- style={{
59525952- width,
59535953- height: 100,
59545954- backgroundColor: 'violet',
59555955- }}
59565956- />
35193519+ <View style={styles.container}>
35203520+ <Animated.View style={[styles.box, style]} />
35213521+ <Button title="shake" onPress={handlePress} />
35223522+ </View>
59573523 );
59583524}
59593525```
5960352659615961-### Using a Shared Value
59625962-59635963-Create 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.
35273527+### Running Animations in a Sequence
5964352859655965-Access and modify values stored in shared values using their `.value` property:
35293529+To enhance the animation, use `withSequence` to chain animations. This modifier starts the next animation when the previous one ends.
5966353059673531```typescript
59685968-import { Button, View } from 'react-native';
59695969-import Animated, { useSharedValue } from 'react-native-reanimated';
35323532+import { withSequence } from "react-native-reanimated"
5970353359715971-export default function App() {
59725972- const width = useSharedValue(100);
35343534+function App() {
35353535+ sv.value = withSequence(withTiming(50), withTiming(0))
35363536+}
35373537+```
5973353859745974- const handlePress = () => {
59755975- width.value = width.value + 50;
59765976- };
35393539+Improved example:
5977354059785978- return (
59795979- <View style={{ flex: 1, alignItems: 'center' }}>
59805980- <Animated.View
59815981- style={{
59825982- width,
59835983- height: 100,
59845984- backgroundColor: 'violet',
59855985- }}
59865986- />
59875987- <Button onPress={handlePress} title="Click me" />
59885988- </View>
59895989- );
35413541+```typescript
35423542+const TIME = 250
35433543+35443544+const handlePress = () => {
35453545+ offset.value = withSequence(
35463546+ // start from -OFFSET
35473547+ withTiming(-OFFSET, { duration: TIME / 2 }),
35483548+ // shake between -OFFSET and OFFSET 5 times
35493549+ withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
35503550+ // go back to 0 at the end
35513551+ withTiming(0, { duration: TIME / 2 })
35523552+ )
59903553}
59913554```
5992355559935993-Avoid directly modifying shared values without using the `.value` property, as in `sv.value = sv.value + 100`.
59945994-59955995-### Using an Animation Function
35563556+### Starting the Animation with Delay
5996355759975997-To animate smoothly, import and use the `withSpring` function. Wrap it around the new width value to create a spring animation:
35583558+Add suspense by delaying the animation start using `withDelay`.
5998355959993560```typescript
60006000-import { Button, View } from 'react-native';
60016001-import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
35613561+import { withDelay } from "react-native-reanimated"
35623562+35633563+function App() {
35643564+ sv.value = withDelay(500, withTiming(0))
35653565+}
35663566+```
6002356760036003-export default function App() {
60046004- const width = useSharedValue(100);
35683568+Final example:
6005356960066006- const handlePress = () => {
60076007- width.value = withSpring(width.value + 50);
60086008- };
35703570+```typescript
35713571+const OFFSET = 40
35723572+const TIME = 250
35733573+const DELAY = 400
6009357460106010- return (
60116011- <View style={{ flex: 1, alignItems: 'center' }}>
60126012- <Animated.View
60136013- style={{
60146014- width,
60156015- height: 100,
60166016- backgroundColor: 'violet',
60176017- }}
60186018- />
60196019- <Button onPress={handlePress} title="Click me" />
60206020- </View>
60216021- );
35753575+const handlePress = () => {
35763576+ offset.value = withDelay(
35773577+ DELAY,
35783578+ withSequence(
35793579+ // start from -OFFSET
35803580+ withTiming(-OFFSET, { duration: TIME / 2 }),
35813581+ // shake between -OFFSET and OFFSET 5 times
35823582+ withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
35833583+ // go back to 0 at the end
35843584+ withTiming(0, { duration: TIME / 2 })
35853585+ )
35863586+ )
60223587}
60233588```
6024358960256025-This creates a bouncy spring animation for the element's width.
60266026-60273590### Summary
6028359160296029-In this section, you learned about:
60306030-60316031-- `Animated` components to define animatable elements.
60326032-- Shared values as the driving factor of animations using `useSharedValue`.
60336033-- Accessing and modifying shared values via their `.value` property (e.g., `sv.value = 100;`).
60346034-- Creating smooth animations by modifying shared values with functions like `withSpring`.
35923592+- **Modifiers**: `withRepeat`, `withSequence`, and `withDelay`.
35933593+- **`withRepeat`**: Repeats an animation a specified number of times or indefinitely.
35943594+- **`withSequence`**: Chains animations to run sequentially.
35953595+- **`withDelay`**: Delays the start of an animation.
6035359660363597### What's Next?
6037359860386038-In the next section, you'll explore animating styles and props using `useAnimatedStyle` and `useAnimatedProps` hooks.
35993599+Explore handling `Tap` and `Pan` gestures, and learn about the `withDecay` animation function.
6039360060403601## withDecay
60413602···61313692|-|-|-|
61323693|✅|✅|✅|
6133369461346134-## runOnRuntime
36953695+## createWorkletRuntime
6135369661366136-The `runOnRuntime` function allows you to execute workletized functions asynchronously on a separate worklet runtime, which operates on a different thread.
36973697+The `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.
6137369861383699### Reference
37003700+37013701+#### Usage in JavaScript
6139370261403703```typescript
61416141-import { createWorkletRuntime, runOnRuntime } from "react-native-reanimated"
61426142-61436143-const workletRuntime = createWorkletRuntime("background")
37043704+import { createWorkletRuntime } from "react-native-reanimated"
6144370561453706function App() {
61466146- // Example usage in an event handler or effect
61476147- runOnRuntime(workletRuntime, (greeting) => {
61486148- console.log(`${greeting} from a separate thread`)
61496149- })("Howdy")
61506150-61516151- // ...
37073707+ const runtime = createWorkletRuntime("background")
61523708}
61533709```
6154371061556155-#### Arguments
37113711+#### Usage in C++
6156371261576157-##### workletRuntime
37133713+```cpp
37143714+auto runtime = reanimated::extractWorkletRuntime(rt, runtimeValue);
6158371561596159-A reference to the worklet runtime created using `createWorkletRuntime`.
37163716+jsi::Runtime &rt = runtime->getJSIRuntime();
6160371761616161-##### fn
37183718+auto worklet = reanimated::extractShareableOrThrow<reanimated::ShareableWorklet>(rt, workletValue);
6162371961636163-A 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)`.
37203720+runtime->runGuarded(worklet, ...args);
37213721+```
6164372261656165-#### Returns
37233723+#### Arguments
6166372461676167-`runOnRuntime` returns a function that accepts arguments for the function provided as its first argument.
37253725+- **`name`**: A string identifier for the runtime that will appear in device lists within Chrome DevTools.
6168372661696169-**Note:** Ensure you call the function returned from `runOnRuntime`.
37273727+- **`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.
37283728+37293729+#### Returns
37303730+37313731+The `createWorkletRuntime` function returns a `WorkletRuntime`, which is represented as a `jsi::HostObject<reanimated::WorkletRuntime>`.
6170373261713733### Remarks
6172373461736173-- A common mistake is to execute a function inside of `runOnRuntime` incorrectly, such as: ~~`runOnRuntime(myWorklet(10))()`~~. The correct usage is `runOnRuntime(myWorklet)(10)`.
37353735+- 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.
6174373661756175-- 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.
37373737+- 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.
6176373861776177-- `runOnRuntime` can be called on any runtime, including the RN runtime, UI runtime, and other worklet runtimes.
37393739+- 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`.
6178374061796179-- 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.
37413741+- 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.
6180374261813743### Platform Compatibility
61823744···61843746|-|-|-|
61853747|✅|✅|❌|
6186374861876187-## Canceling Animations with `cancelAnimation`
37493749+## interpolate
37503750+37513751+The `interpolate` function is used to map a numeric value from one specified range to another using linear interpolation.
37523752+37533753+### Reference Usage
37543754+37553755+```typescript
37563756+import { interpolate, Extrapolation } from "react-native-reanimated"
37573757+37583758+function App() {
37593759+ const animatedStyle = useAnimatedStyle(() => ({
37603760+ opacity: interpolate(sv.value, [0, 100], [0, 1], Extrapolation.CLAMP),
37613761+ }))
37623762+}
37633763+```
37643764+37653765+#### Parameters
37663766+37673767+- **`value`**: A numeric value that will be mapped to the specified `output` range.
37683768+37693769+- **`input`**: An array of numbers defining the input range for interpolation.
37703770+37713771+- **`output`**: An array of numbers defining the output range for interpolation, which should have at least as many points as the input range.
37723772+37733773+- **`extrapolate` (Optional)**: Determines behavior when `value` is outside the `input` range. Defaults to `Extrapolation.EXTEND`.
37743774+37753775+ Available options:
37763776+37773777+ - `Extrapolation.EXTEND`: Predicts values beyond the output range.
37783778+ - `Extrapolation.CLAMP`: Clamps the value to the edge of the output range.
37793779+ - `Extrapolation.IDENTITY`: Returns the provided value unchanged.
37803780+37813781+ String equivalents include `"extend"`, `"clamp"`, and `"identity"`.
37823782+37833783+ To apply extrapolation to a specific edge, use an object:
37843784+37853785+ ```typescript
37863786+ const opacity = interpolate(sv.value, [0, 100], [0, 1], {
37873787+ extrapolateLeft: Extrapolation.CLAMP,
37883788+ })
37893789+ ```
37903790+37913791+#### Return Value
37923792+37933793+The `interpolate` function returns a value mapped within the specified output range.
37943794+37953795+### Platform Compatibility
37963796+37973797+|Android|iOS|Web|
37983798+|-|-|-|
37993799+|✅|✅|✅|
38003800+38013801+## cancelAnimation
6188380261893803The `cancelAnimation` function is used to stop an ongoing animation associated with a shared value in React Native Reanimated.
61903804···6226384062273841This function is compatible across Android, iOS, and web platforms.
6228384262296229-## createWorkletRuntime
38433843+## Clamp Function in React Native Reanimated
6230384462316231-The `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.
38453845+The `clamp` function is used to restrict a value within a specified range, ensuring it does not exceed the defined minimum and maximum bounds.
6232384662333847### Reference
6234384862356235-#### Usage in JavaScript
38493849+```typescript
38503850+import { clamp } from "react-native-reanimated"
38513851+38523852+function App() {
38533853+ const result = clamp(sv.value, 0, 100)
38543854+}
38553855+```
38563856+38573857+#### Arguments
38583858+38593859+- **`value`**: A numeric value that will be returned if it falls within the specified `min` and `max` range.
38603860+38613861+- **`min`**: The lower bound. If the provided `value` is less than this number, `min` will be returned.
38623862+38633863+- **`max`**: The upper bound. If the provided `value` exceeds this number, `max` will be returned.
38643864+38653865+#### Returns
38663866+38673867+The function returns a numeric value that lies between the specified `min` and `max` bounds.
38683868+38693869+### Example Usage
6236387062373871```typescript
62386238-import { createWorkletRuntime } from "react-native-reanimated"
38723872+import { clamp } from "react-native-reanimated"
6239387362403874function App() {
62416241- const runtime = createWorkletRuntime("background")
38753875+ const constrainedValue = clamp(150, 0, 100) // Result will be 100
62423876}
62433877```
6244387862456245-#### Usage in C++
38793879+### Platform Compatibility
6246388062476247-```cpp
62486248-auto runtime = reanimated::extractWorkletRuntime(rt, runtimeValue);
38813881+|Android|iOS|Web|
38823882+|-|-|-|
38833883+|✅|✅|✅|
38843884+38853885+This function is compatible across Android, iOS, and Web platforms.
38863886+38873887+## interpolateColor
38883888+38893889+The `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.
38903890+38913891+### Reference Example
38923892+38933893+```typescript
38943894+import { interpolateColor } from 'react-native-reanimated';
38953895+38963896+function App() {
38973897+ const progress = useSharedValue(0);
6249389862506250-jsi::Runtime &rt = runtime->getJSIRuntime();
38993899+ const animatedStyle = useAnimatedStyle(() => {
39003900+ return {
39013901+ backgroundColor: interpolateColor(
39023902+ progress.value,
39033903+ [0, 1],
39043904+ ['red', 'green']
39053905+ ),
39063906+ };
39073907+ });
6251390862526252-auto worklet = reanimated::extractShareableOrThrow<reanimated::ShareableWorklet>(rt, workletValue);
39093909+ // ...
6253391062546254-runtime->runGuarded(worklet, ...args);
39113911+ return <Animated.View style={[{ width: 100, height: 100 }, animatedStyle]} />;
39123912+}
62553913```
6256391462573915#### Arguments
6258391662596259-- **`name`**: A string identifier for the runtime that will appear in device lists within Chrome DevTools.
39173917+- **`value`**: A number from the input range that is mapped to the output range.
39183918+39193919+- **`input`**: An array of numbers specifying the input range for interpolation. The values should be in increasing order.
39203920+39213921+- **`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.
6260392262616261-- **`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.
39233923+- **`colorSpace`** *(Optional)*: Specifies the color space for interpolation, either `'HSV'` or `'RGB'`. Defaults to `'RGB'`.
39243924+39253925+- **`options`** *(Optional)*: Additional parameters for color interpolation:
39263926+39273927+ |Options|Type|Default|Description|
39283928+ |-|-|-|-|
39293929+ |`gamma`|`number`|2.2|Gamma parameter used in gamma correction.|
39303930+ |`useCorrectedHSVInterpolation`|`boolean`|true|Reduces the number of hues during interpolation by treating HSV as circular.|
39313931+39323932+#### Options Explanation
39333933+39343934+- **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.
39353935+39363936+- **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).
6262393762633938#### Returns
6264393962656265-The `createWorkletRuntime` function returns a `WorkletRuntime`, which is represented as a `jsi::HostObject<reanimated::WorkletRuntime>`.
39403940+The function returns an interpolated color in `rgba(r, g, b, a)` format within the specified output range.
6266394162673942### Remarks
6268394362696269-- 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.
39443944+- The function operates similarly to the `interpolate` function but specifically outputs a color string in `rgba(r, g, b, a)` notation.
39453945+39463946+### Platform Compatibility
39473947+39483948+|Android|iOS|Web|
39493949+|-|-|-|
39503950+|✅|✅|✅|
39513951+39523952+This function is versatile and compatible across major platforms, making it ideal for cross-platform applications.
39533953+39543954+## withSequence
39553955+39563956+`withSequence` is an animation modifier that allows animations to be executed in a sequential order.
39573957+39583958+### Reference
39593959+39603960+```typescript
39613961+import { withSequence } from "react-native-reanimated"
39623962+39633963+function App() {
39643964+ sv.value = withSequence(withTiming(50), withTiming(0))
39653965+ // ...
39663966+}
39673967+```
39683968+39693969+#### Arguments
39703970+39713971+##### `reduceMotion` (Optional)
39723972+39733973+A parameter that specifies how the animation should respond to the device's reduced motion accessibility setting.
39743974+39753975+##### `...animations`
39763976+39773977+Any number of animation objects that will be executed in sequence.
39783978+39793979+#### Returns
39803980+39813981+The `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`.
39823982+39833983+### Example
39843984+39853985+### Platform Compatibility
39863986+39873987+|Android|iOS|Web|
39883988+|-|-|-|
39893989+|✅|✅|✅|
6270399062716271-- 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.
39913991+## scrollTo
6272399262736273-- 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`.
39933993+The `scrollTo` function allows you to synchronously scroll a component to a specified X or Y offset.
6274399462756275-- 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.
39953995+### Reference
39963996+39973997+```typescript
39983998+import { scrollTo } from 'react-native-reanimated';
39993999+40004000+function App() {
40014001+ const animatedRef = useAnimatedRef();
40024002+ const scrollY = useSharedValue(0);
40034003+40044004+ useDerivedValue(() => {
40054005+ scrollTo(animatedRef, 0, scrollY.value, true);
40064006+ });
40074007+40084008+ return (
40094009+ <Animated.ScrollView ref={animatedRef}>{/* ... */}</Animated.ScrollView>
40104010+ );
40114011+}
40124012+```
40134013+40144014+#### Arguments
40154015+40164016+- **`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.
40174017+40184018+- **`x`**: The pixel value for horizontal scrolling on the X axis.
40194019+40204020+- **`y`**: The pixel value for vertical scrolling on the Y axis.
40214021+40224022+- **`animated`**: A boolean indicating if the scroll should be smooth (`true`) or instant (`false`).
40234023+40244024+#### Returns
40254025+40264026+The `scrollTo` function returns `undefined`.
40274027+40284028+### Remarks
40294029+40304030+- The `scrollTo` function must be invoked from the UI thread.
40314031+- It supports `Animated.FlatList`.
40324032+- Typically works with other ScrollView-like and FlatList-like components if they use a `ScrollView` internally and are animated.
40334033+- Scrollable components need to implement the `getScrollableNode` method (and `getNativeScrollRef` for New Architecture) to be compatible with `scrollTo`.
6276403462774035### Platform Compatibility
6278403662794037|Android|iOS|Web|
62804038|-|-|-|
62816281-|✅|✅|❌|
40394039+|✅|✅|✅|
40404040+40414041+## getRelativeCoords Functionality
40424042+40434043+The `getRelativeCoords` function is used to determine the screen location relative to a specified view.
6282404462836283-```markdown
62846284-# `useAnimatedGestureHandler`
40454045+### Reference Code
40464046+40474047+```typescript
40484048+import { getRelativeCoords } from 'react-native-reanimated';
6285404962866286-**Note:** This API has been deprecated. It no longer receives updates and will be removed in a future major release of Reanimated.
40504050+const Comp = () => {
40514051+ const animatedRef = useAnimatedRef();
6287405262886288-## Overview
40534053+ const gestureHandler = useAnimatedGestureHandler({
40544054+ onEnd: (event) => {
40554055+ const coords = getRelativeCoords(
40564056+ animatedRef,
40574057+ event.absoluteX,
40584058+ event.absoluteY
40594059+ );
40604060+ },
40614061+ });
6289406262906290-The `useAnimatedGestureHandler` function is part of the Reanimated library, which provides tools for creating smooth animations on React Native applications. However, due to its deprecation status, developers are advised to seek alternative solutions or APIs that offer similar functionality but with ongoing support and updates.
40634063+ return (
40644064+ <View ref={animatedRef}>
40654065+ <PanGestureHandler onGestureEvent={gestureHandler}>
40664066+ <Animated.View style={[styles.box]} />
40674067+ </PanGestureHandler>
40684068+ </View>
40694069+ );
40704070+};
62914071```
6292407262936293-## Applying Modifiers in Reanimated
40734073+### Arguments
40744074+40754075+- **`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.
40764076+40774077+- **`absoluteX`**: A number representing the absolute x-coordinate.
40784078+40794079+- **`absoluteY`**: A number representing the absolute y-coordinate.
6294408062956295-Reanimated provides built-in modifiers for customizing animations: `withRepeat`, `withSequence`, and `withDelay`. This guide demonstrates how to use these modifiers by creating a shake animation.
40814081+### Returns
6296408262976297-### Starting Point
40834083+An object containing:
6298408462996299-We'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.
40854085+- `x`: The relative x-coordinate.
40864086+- `y`: The relative y-coordinate.
40874087+40884088+### Platform Compatibility
40894089+40904090+|Android|iOS|Web|
40914091+|-|-|-|
40924092+|✅|✅|✅|
40934093+40944094+## useAnimatedGestureHandler
40954095+40964096+**Warning:**\
40974097+The `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.
40984098+40994099+This hook necessitates that `react-native-gesture-handler` be installed and configured within your project.
41004100+41014101+### Reference
41024102+41034103+```typescript
41044104+import { useAnimatedGestureHandler } from 'react-native-reanimated';
41054105+import { PanGestureHandler } from 'react-native-gesture-handler';
41064106+41074107+function App() {
41084108+ const x = useSharedValue(0);
41094109+41104110+ const gestureHandler = useAnimatedGestureHandler({
41114111+ onStart: (_, ctx) => {
41124112+ ctx.startX = x.value;
41134113+ },
41144114+ onActive: (event, ctx) => {
41154115+ x.value = ctx.startX + event.translationX;
41164116+ },
41174117+ });
41184118+41194119+ return (
41204120+ <PanGestureHandler onGestureEvent={gestureHandler}>
41214121+ <Animated.View />
41224122+ </PanGestureHandler>
41234123+ );
41244124+}
41254125+```
41264126+41274127+#### Arguments
41284128+41294129+##### `gestureHandlers`
41304130+41314131+The 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`.
41324132+41334133+Each 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:
41344134+41354135+- `event` \[object] - an event object containing the payload specific to the type of gesture handler (e.g., `PanGestureHandler`, `RotationGestureHandler`).
41364136+41374137+- `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.
41384138+41394139+##### `dependencies` (Optional)
41404140+41414141+An optional array of dependencies is relevant only when using Reanimated without the Babel plugin on the Web.
41424142+41434143+#### Returns
41444144+41454145+The `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.
41464146+41474147+### Example
41484148+41494149+### Platform Compatibility
41504150+41514151+|Android|iOS|Web|
41524152+|-|-|-|
41534153+|✅|✅|⚠️|
41544154+41554155+- On the Web, it is necessary to pass the returned handler object to both `onGestureEvent` and `onHandlerStateChange` parameters.
41564156+41574157+## useScrollViewOffset Hook
41584158+41594159+The `useScrollViewOffset` hook enables the creation of animations based on a `ScrollView`'s offset. It automatically determines whether the `ScrollView` is oriented horizontally or vertically.
41604160+41614161+### Reference
41624162+41634163+```typescript
41644164+import { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
41654165+41664166+function App() {
41674167+ const animatedRef = useAnimatedRef();
41684168+ const scrollOffset = useScrollViewOffset(animatedRef);
41694169+41704170+ return (
41714171+ <Animated.ScrollView ref={animatedRef}>
41724172+ {/* Content goes here */}
41734173+ </Animated.ScrollView>
41744174+ );
41754175+}
41764176+```
41774177+41784178+#### Arguments
41794179+41804180+##### `animatedRef`
41814181+41824182+An 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.
41834183+41844184+##### `initialRef` (Optional)
41854185+41864186+A shared value that can optionally be updated with the scroll offset. If not provided, a new shared value will be created internally by default.
41874187+41884188+#### Returns
41894189+41904190+The hook returns a shared value representing the current offset of the `ScrollView`.
41914191+41924192+### Example Usage
41934193+41944194+- The `animatedRef` argument can be dynamically changed, and the hook will continue to provide accurate values based on the connected `ScrollView`. For instance:
41954195+41964196+ ```typescript
41974197+ useScrollViewOffset(someState ? someScrollRefA : someScrollRefB)
41984198+ ```
41994199+42004200+### Platform Compatibility
42014201+42024202+|Android|iOS|Web|
42034203+|-|-|-|
42044204+|✅|✅|✅|
42054205+42064206+## measure
42074207+42084208+The `measure` function allows you to synchronously obtain the dimensions and position of a view on the screen, executed on the UI thread.
42094209+42104210+### Reference
42114211+42124212+```typescript
42134213+import { measure } from 'react-native-reanimated';
42144214+42154215+function App() {
42164216+ const animatedRef = useAnimatedRef();
42174217+42184218+ const handlePress = () => {
42194219+ runOnUI(() => {
42204220+ const measurement = measure(animatedRef);
42214221+ if (measurement === null) {
42224222+ return;
42234223+ }
42244224+ // Additional logic can be added here
42254225+ })();
42264226+ };
42274227+42284228+ return <Animated.View ref={animatedRef} />;
42294229+}
42304230+```
42314231+42324232+#### Arguments
42334233+42344234+- **`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.
42354235+42364236+#### Returns
42374237+42384238+The `measure` function returns an object containing:
42394239+42404240+|Field|Description|
42414241+|-|-|
42424242+|`x`|A number representing the X coordinate relative to the parent component.|
42434243+|`y`|A number representing the Y coordinate relative to the parent component.|
42444244+|`width`|A number representing the width of the component.|
42454245+|`height`|A number representing the height of the component.|
42464246+|`pageX`|A number representing the X coordinate relative to the screen.|
42474247+|`pageY`|A number representing the Y coordinate relative to the screen.|
42484248+42494249+Alternatively, it returns `null` if the measurement could not be performed.
42504250+42514251+### Remarks
42524252+42534253+- **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.
42544254+42554255+- **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:
42564256+42574257+ ```typescript
42584258+ function App() {
42594259+ const animatedStyles = useAnimatedStyle(() => {
42604260+ if (_WORKLET) {
42614261+ // Safely use measure here
42624262+ const measurement = measure(animatedRef)
42634263+ }
42644264+ })
42654265+ }
42664266+ ```
42674267+42684268+- **Consecutive Runs**: Subsequent executions of `useAnimatedStyle` occur on the UI thread.
42694269+42704270+- **Alternative for Static Dimensions**: If only static dimensions are needed and measurements aren't used during animations, consider using the `onLayout` property instead.
42714271+42724272+- **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:
42734273+42744274+ ```typescript
42754275+ const animatedRef = useAnimatedRef()
42764276+42774277+ const handlePress = () => {
42784278+ runOnUI(() => {
42794279+ const measurement = measure(animatedRef)
42804280+42814281+ if (measurement === null) {
42824282+ return
42834283+ }
42844284+ // Additional logic can be added here
42854285+ })()
42864286+ }
42874287+ ```
42884288+42894289+- **Rendered Components Only**: `measure` is applicable only to rendered components. For example, measuring off-screen items in a `FlatList` will yield `null`.
42904290+42914291+- **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.
42924292+42934293+### Platform Compatibility
42944294+42954295+|Android|iOS|Web|
42964296+|-|-|-|
42974297+|✅|✅|✅|
42984298+42994299+## useAnimatedReaction
43004300+43014301+The `useAnimatedReaction` hook enables responses to changes in shared values, particularly useful when comparing previous and current values stored within a shared value.
43024302+43034303+### Reference
43044304+43054305+```typescript
43064306+import { useAnimatedReaction } from "react-native-reanimated"
43074307+43084308+function App() {
43094309+ useAnimatedReaction(
43104310+ () => sv.value,
43114311+ (currentValue, previousValue) => {
43124312+ if (currentValue !== previousValue) {
43134313+ // perform an action ✨
43144314+ }
43154315+ }
43164316+ )
43174317+43184318+ // ...
43194319+}
43204320+```
43214321+43224322+#### Arguments
43234323+43244324+##### `prepare`
43254325+43264326+A function returning the value to which you want to react. This returned value serves as the first parameter for the `react` argument.
43274327+43284328+```typescript
43294329+function App() {
43304330+ useAnimatedReaction(
43314331+ () => Math.floor(sv.value),
43324332+ (currentValue, previousValue) => {
43334333+ // ...
43344334+ }
43354335+ )
43364336+}
43374337+```
43384338+43394339+##### `react`
43404340+43414341+A 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`.
43424342+43434343+```typescript
43444344+function App() {
43454345+ useAnimatedReaction(
43464346+ () => Math.floor(sv.value),
43474347+ (currentValue, previousValue) => {
43484348+ // ...
43494349+ }
43504350+ )
43514351+}
43524352+```
43534353+43544354+##### `dependencies` (Optional)
43554355+43564356+An optional array of dependencies. This is only relevant when using Reanimated without the Babel plugin on the Web.
43574357+43584358+#### Returns
43594359+43604360+The `useAnimatedReaction` hook returns `undefined`.
43614361+43624362+### Example
43634363+43644364+### Remarks
43654365+43664366+- Avoid mutating the same shared value in the `react` function that was used in the `prepare` function to prevent infinite loops.
43674367+43684368+```typescript
43694369+function App() {
43704370+ useAnimatedReaction(
43714371+ () => width.value,
43724372+ (currentValue) => {
43734373+ // 🚨 An infinite loop!
43744374+ width.value += currentValue
43754375+ }
43764376+ )
43774377+}
43784378+```
43794379+43804380+- Callbacks for both `prepare` and `react` are automatically workletized, running on the UI thread.
43814381+43824382+- While you can use `useAnimatedReaction` to react to any stateful React value, it's generally better to use a `useEffect` for such purposes.
43834383+43844384+### Platform Compatibility
43854385+43864386+|Android|iOS|Web|
43874387+|-|-|-|
43884388+|✅|✅|✅|
43894389+43904390+## Animating styles and props
43914391+43924392+In this section, we explore different methods for passing animation styles to components. We will differentiate between animating styles and props using `useAnimatedStyle` and `useAnimatedProps`.
43934393+43944394+### Animating Styles
43954395+43964396+Previously, 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.
43974397+43984398+```typescript
43994399+import Animated, { useSharedValue } from 'react-native-reanimated';
44004400+44014401+function App() {
44024402+ const width = useSharedValue(100);
44034403+44044404+ return <Animated.View style={{ width }} />;
44054405+}
44064406+```
44074407+44084408+For example, multiplying a shared value before assigning it to the `style` prop is not possible:
44094409+44104410+```typescript
44114411+<Animated.View style={{ width: width * 5 }} /> // This won't work
44124412+```
44134413+44144414+Consider an example where a box moves right on button press:
44154415+44164416+```typescript
44174417+import { View, Button } from 'react-native';
44184418+import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
44194419+44204420+function App() {
44214421+ const translateX = useSharedValue(0);
44224422+44234423+ const handlePress = () => {
44244424+ translateX.value = withSpring(translateX.value + 50);
44254425+ };
44264426+44274427+ return (
44284428+ <View style={styles.container}>
44294429+ <Animated.View style={[styles.box, { transform: [{ translateX }] }]} />
44304430+ <Button onPress={handlePress} title="Click me" />
44314431+ </View>
44324432+ );
44334433+}
44344434+```
44354435+44364436+To customize shared value changes based on user input, `useAnimatedStyle` is used for more control and flexibility:
6300443763014438```typescript
63024439export default function App() {
63036303- const offset = useSharedValue<number>(0);
44404440+ const translateX = useSharedValue<number>(0);
44414441+44424442+ const handlePress = () => {
44434443+ translateX.value += 50;
44444444+ };
6304444563056305- const style = useAnimatedStyle(() => ({
63066306- transform: [{ translateX: offset.value }],
44464446+ const animatedStyles = useAnimatedStyle(() => ({
44474447+ transform: [{ translateX: withSpring(translateX.value * 2) }],
63074448 }));
6308444963096309- const OFFSET = 40;
44504450+ return (
44514451+ <>
44524452+ <Animated.View style={[styles.box, animatedStyles]} />
44534453+ <View style={styles.container}>
44544454+ <Button onPress={handlePress} title="Click me" />
44554455+ </View>
44564456+ </>
44574457+ );
44584458+}
44594459+```
44604460+44614461+`useAnimatedStyle` allows access to the shared value's `.value`, enabling operations like multiplication before assigning it to `style`. It also centralizes animation logic.
44624462+44634463+### Animating Props
44644464+44654465+While many values are animated via the `style` property, sometimes props need animating. For example, SVG elements use props instead of styles:
44664466+44674467+```typescript
44684468+<Circle cx="50" cy="50" r="10" fill="blue" />
44694469+```
44704470+44714471+To animate non-Reanimated components' props, wrap them with `createAnimatedComponent`:
44724472+44734473+```typescript
44744474+import Animated from "react-native-reanimated"
44754475+import { Circle } from "react-native-svg"
44764476+44774477+const AnimatedCircle = Animated.createAnimatedComponent(Circle)
44784478+```
44794479+44804480+Animating the radius of an SVG circle can be done by passing a shared value as a prop:
44814481+44824482+```typescript
44834483+import { useSharedValue } from 'react-native-reanimated';
44844484+import { Svg } from 'react-native-svg';
44854485+44864486+function App() {
44874487+ const r = useSharedValue(10);
44884488+44894489+ return (
44904490+ <Svg>
44914491+ <AnimatedCircle cx="50" cy="50" r={r} fill="blue" />
44924492+ </Svg>
44934493+ );
44944494+}
44954495+```
44964496+44974497+For encapsulating animation logic and accessing `.value`, `useAnimatedProps` is used:
44984498+44994499+```typescript
45004500+const AnimatedCircle = Animated.createAnimatedComponent(Circle);
45014501+45024502+export default function App() {
45034503+ const r = useSharedValue<number>(20);
6310450463114505 const handlePress = () => {
63126312- offset.value = withTiming(OFFSET);
45064506+ r.value += 10;
63134507 };
6314450845094509+ const animatedProps = useAnimatedProps(() => ({
45104510+ r: withTiming(r.value),
45114511+ }));
45124512+63154513 return (
63164514 <View style={styles.container}>
63176317- <Animated.View style={[styles.box, style]} />
63186318- <Button title="shake" onPress={handlePress} />
45154515+ <Svg style={styles.svg}>
45164516+ <AnimatedCircle
45174517+ cx="50%"
45184518+ cy="50%"
45194519+ fill="#b58df1"
45204520+ animatedProps={animatedProps}
45214521+ />
45224522+ </Svg>
45234523+ <Button onPress={handlePress} title="Click me" />
63194524 </View>
63204525 );
63214526}
63224527```
6323452863246324-### Repeating an Animation
45294529+In `useAnimatedProps`, return an object with animatable props, then pass it to the `animatedProps` prop of an Animated component.
6325453063266326-To create a shake effect, use the `withRepeat` modifier. This allows you to repeat an animation multiple times or indefinitely.
45314531+### Summary
45324532+45334533+- Inline styles are simple but limited for complex animations.
45344534+- Props differ from styles as they aren't passed via the `style` object.
45354535+- `useAnimatedStyle` and `useAnimatedProps` provide access to shared values' `.value`, enhancing animation control.
45364536+- Custom animatable components can be created with `Animated.createAnimatedComponent`.
45374537+45384538+### What's Next?
45394539+45404540+In the next section, we'll delve into animation functions and customizing their behavior.
45414541+45424542+## useFrameCallback in React Native Reanimated (Version: 3.x)
45434543+45444544+### Overview
45454545+45464546+The `useFrameCallback` hook allows you to execute a function on every frame update within your application.
45474547+45484548+### Reference
6327454963284550```typescript
63296329-import { withRepeat } from "react-native-reanimated"
45514551+import { useFrameCallback } from 'react-native-reanimated';
6330455263314553function App() {
63326332- sv.value = withRepeat(withTiming(50), 5)
45544554+ const frameCallback = useFrameCallback((frameInfo) => {
45554555+ // Increment a value with each frame update
45564556+ sv.value += 1;
45574557+ });
45584558+45594559+ return (
45604560+ <Button
45614561+ title="Start/Stop"
45624562+ onPress={() => frameCallback.setActive(!frameCallback.isActive)}
45634563+ />
45644564+ );
63334565}
63344566```
6335456763366336-Pass a number for repetitions or a non-positive value for infinite repetition. Use `true` as the third argument to reverse the animation direction.
45684568+#### Arguments
6337456963386338-Updated example:
45704570+##### `callback`
45714571+45724572+- A function that runs on every frame update.
45734573+- Receives a `frameInfo` object with the following properties:
45744574+ - `timestamp`: The system time (in milliseconds) when the last frame was rendered.
45754575+ - `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.
45764576+ - `timeSinceFirstFrame`: The time (in milliseconds) elapsed since the callback was activated.
45774577+45784578+##### `autostart` (Optional)
45794579+45804580+- Determines if the callback should start automatically. Defaults to `true`.
45814581+45824582+#### Returns
45834583+45844584+The `useFrameCallback` hook returns an object with these properties:
45854585+45864586+- `setActive`: A function to start or stop the frame callback.
45874587+- `isActive`: A boolean indicating whether the callback is currently running.
45884588+- `callbackId`: A unique identifier for the frame callback.
45894589+45904590+### Remarks
45914591+45924592+- The function provided in the `callback` argument is automatically workletized and executed on the UI thread.
45934593+45944594+### Platform Compatibility
45954595+45964596+|Android|iOS|Web|
45974597+|-|-|-|
45984598+|✅|✅|✅|
45994599+46004600+- Reference
46014601+ - Arguments
46024602+ - Returns
46034603+- Example
46044604+- Remarks
46054605+- Platform compatibility
46064606+46074607+## Handling gestures
46084608+46094609+This 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.
46104610+46114611+Ensure you've completed the Gesture Handler installation steps before proceeding.
46124612+46134613+### Handling Tap Gestures
46144614+46154615+We begin with tap gestures, which detect brief screen touches. These can be used for custom buttons or pressable elements.
46164616+46174617+In this example, a circle grows and changes color upon touch.
46184618+46194619+First, wrap your app in `GestureHandlerRootView` to ensure gesture functionality:
46204620+46214621+```typescript
46224622+import { GestureHandlerRootView } from 'react-native-gesture-handler';
46234623+46244624+function App() {
46254625+ return (
46264626+ <GestureHandlerRootView style={{ flex: 1 }}>
46274627+ {/* rest of the app */}
46284628+ </GestureHandlerRootView>
46294629+ );
46304630+}
46314631+```
46324632+46334633+Define tap gestures using `Gesture.Tap()` and chain methods like `onBegin`, `onStart`, `onEnd`, or `onFinalize` to update shared values:
6339463463404635```typescript
63414636export default function App() {
63426342- const offset = useSharedValue<number>(0);
46374637+ const pressed = useSharedValue<boolean>(false);
6343463863446344- const style = useAnimatedStyle(() => ({
63456345- transform: [{ translateX: offset.value }],
63466346- }));
46394639+ const tap = Gesture.Tap()
46404640+ .onBegin(() => {
46414641+ pressed.value = true;
46424642+ })
46434643+ .onFinalize(() => {
46444644+ pressed.value = false;
46454645+ });
46464646+```
6347464763486348- const OFFSET = 40;
46484648+Access shared values safely as gesture callbacks are automatically workletized.
46494649+46504650+Define animation logic using `withTiming` in `useAnimatedStyle`:
46514651+46524652+```typescript
46534653+const animatedStyles = useAnimatedStyle(() => ({
46544654+ backgroundColor: pressed.value ? "#FFE04B" : "#B58DF1",
46554655+ transform: [{ scale: withTiming(pressed.value ? 1.2 : 1) }],
46564656+}))
46574657+```
6349465863506350- const handlePress = () => {
63516351- offset.value = withRepeat(withTiming(OFFSET), 5, true);
63526352- };
46594659+Pass the gesture to `GestureDetector` and apply `animatedStyles`:
6353466046614661+```typescript
63544662 return (
63556355- <View style={styles.container}>
63566356- <Animated.View style={[styles.box, style]} />
63576357- <Button title="shake" onPress={handlePress} />
63586358- </View>
46634663+ <GestureHandlerRootView style={styles.container}>
46644664+ <View style={styles.container}>
46654665+ <GestureDetector gesture={tap}>
46664666+ <Animated.View style={[styles.circle, animatedStyles]} />
46674667+ </GestureDetector>
46684668+ </View>
46694669+ </GestureHandlerRootView>
63594670 );
63604671}
63614672```
6362467363636363-### Running Animations in a Sequence
46744674+### Handling Pan Gestures
46754675+46764676+Enhance the circle by making it draggable and bouncing back to its starting position upon release. Retain color highlight and scale effects.
46774677+46784678+Switch from `Tap` to `Pan` gesture and add an `onChange` method:
46794679+46804680+```typescript
46814681+const offset = useSharedValue<number>(0);
46824682+46834683+const pan = Gesture.Pan()
46844684+ .onBegin(() => {
46854685+ pressed.value = true;
46864686+ })
46874687+ .onChange((event) => {
46884688+ offset.value = event.translationX;
46894689+ })
46904690+ .onFinalize(() => {
46914691+ offset.value = withSpring(0);
46924692+ pressed.value = false;
46934693+```
6364469463656365-To enhance the animation, use `withSequence` to chain animations. This modifier starts the next animation when the previous one ends.
46954695+Use `translationX` from the event data to move the circle. Reset `offset.value` in `onFinalize` using `withSpring`.
46964696+46974697+Adjust `useAnimatedStyle` for handling offset:
6366469863674699```typescript
63686368-import { withSequence } from "react-native-reanimated"
47004700+const animatedStyles = useAnimatedStyle(() => ({
47014701+ transform: [
47024702+ { translateX: offset.value },
47034703+ { scale: withTiming(pressed.value ? 1.2 : 1) },
47044704+ ],
47054705+ backgroundColor: pressed.value ? "#FFE04B" : "#b58df1",
47064706+}))
47074707+```
47084708+47094709+### Using `withDecay`
47104710+47114711+`withDecay` retains gesture velocity for decelerating animations.
47124712+47134713+Pass final velocity in `onFinalize` to `withDecay`:
47144714+47154715+```typescript
47164716+const pan = Gesture.Pan()
47174717+ .onChange((event) => {
47184718+ offset.value += event.changeX;
47194719+ })
47204720+ .onFinalize((event) => {
47214721+ offset.value = withDecay({
47224722+ velocity: event.velocityX,
47234723+ rubberBandEffect: true,
47244724+ clamp: [
47254725+ -(width.value / 2) + SIZE / 2 + BOUNDARY_OFFSET,
47264726+ width.value / 2 - SIZE / 2 - BOUNDARY_OFFSET,
47274727+```
47284728+47294729+Ensure the square stays within screen bounds.
47304730+47314731+Explore `withDecay` API for more configuration options.
47324732+47334733+### Summary
47344734+47354735+This section covered gesture handling with Reanimated and Gesture Handler, focusing on `Tap`, `Pan`, and `withDecay`. Key points include:
47364736+47374737+- Integration of Reanimated with React Native Gesture Handler.
47384738+- Creation of gestures like `Gesture.Pan()` or `Gesture.Tap()`.
47394739+- Accessing shared values in gesture callbacks without extra boilerplate.
47404740+- Using `withDecay` for decelerating animations based on gesture velocity.
47414741+47424742+### What's Next?
47434743+47444744+Explore 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.
47454745+47464746+## withRepeat
47474747+47484748+`withRepeat` is an animation modifier that allows you to repeat a specified animation a certain number of times or indefinitely.
47494749+47504750+### Reference
47514751+47524752+```typescript
47534753+import { withRepeat } from "react-native-reanimated"
6369475463704755function App() {
63716371- sv.value = withSequence(withTiming(50), withTiming(0))
47564756+ sv.value = withRepeat(withSpring(0), 5)
47574757+ // ...
63724758}
63734759```
6374476063756375-Improved example:
47614761+#### Arguments
47624762+47634763+##### `animation`
47644764+47654765+The animation object you wish to repeat.
47664766+47674767+##### `numberOfReps` (Optional)
47684768+47694769+Specifies how many times the animation should be repeated. The default is `2`.
47704770+47714771+A 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.
47724772+47734773+##### `reverse` (Optional)
47744774+47754775+Determines whether the animation should alternate directions with each repetition. The default setting is `false`.
47764776+47774777+This feature only supports direct animation functions like `withSpring` and does not work with other animation modifiers such as `withSequence`.
47784778+47794779+##### `callback` (Optional)
47804780+47814781+A function that executes upon the completion of the animation. If the animation is canceled, the callback receives `false`; otherwise, it receives `true`.
47824782+47834783+##### `reduceMotion` (Optional)
47844784+47854785+Controls how the animation responds to the device's reduced motion accessibility setting.
47864786+47874787+#### Returns
47884788+47894789+The `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`.
47904790+47914791+### Remarks
47924792+47934793+- The callback provided in the fourth argument is automatically workletized and executed on the UI thread.
47944794+47954795+### Platform Compatibility
47964796+47974797+|Android|iOS|Web|
47984798+|-|-|-|
47994799+|✅|✅|✅|
48004800+48014801+## useComposedEventHandler
48024802+48034803+The `useComposedEventHandler` hook allows you to combine multiple event handlers, such as those created with `useAnimatedScrollHandler`, into a single handler.
48044804+48054805+### Reference Example
6376480663774807```typescript
63786378-const TIME = 250
48084808+import Animated, {
48094809+ useAnimatedScrollHandler,
48104810+ useComposedEventHandler,
48114811+} from 'react-native-reanimated';
48124812+48134813+function ComposedEventHandlerExample() {
48144814+ const onScrollHandler1 = useAnimatedScrollHandler({
48154815+ onScroll(e) {
48164816+ console.log('Scroll handler 1 onScroll event');
48174817+ },
48184818+ });
48194819+48204820+ const onScrollHandler2 = useAnimatedScrollHandler({
48214821+ onScroll(e) {
48224822+ console.log('Scroll handler 2 onScroll event');
48234823+ },
48244824+ });
48254825+48264826+ const composedHandler = useComposedEventHandler([
48274827+ onScrollHandler1,
48284828+ onScrollHandler2,
48294829+ ]);
6379483063806380-const handlePress = () => {
63816381- offset.value = withSequence(
63826382- // start from -OFFSET
63836383- withTiming(-OFFSET, { duration: TIME / 2 }),
63846384- // shake between -OFFSET and OFFSET 5 times
63856385- withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
63866386- // go back to 0 at the end
63876387- withTiming(0, { duration: TIME / 2 })
63886388- )
48314831+ return (
48324832+ <View style={styles.container}>
48334833+ <Animated.ScrollView style={styles.scroll} onScroll={composedHandler}>
48344834+ <Content />
48354835+ </Animated.ScrollView>
48364836+ </View>
48374837+ );
63894838}
63904839```
6391484063926392-### Starting the Animation with Delay
48414841+#### Arguments
48424842+48434843+- **`handlers`**: An array of event handlers created using the `useEvent` hook. The `useComposedEventHandler` hook updates whenever there are changes in these handlers.
48444844+48454845+#### Returns
48464846+48474847+The 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.
48484848+48494849+### Remarks
48504850+48514851+- 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.
48524852+- It functions effectively when used with multiple `Animated components`, triggering event callbacks for each connected component.
48534853+48544854+### Platform Compatibility
48554855+48564856+|Android|iOS|Web|
48574857+|-|-|-|
48584858+|✅|✅|✅|
48594859+48604860+## withDelay
48614861+48624862+`withDelay` is an animation modifier that allows you to initiate an animation after a specified delay period.
6393486363946394-Add suspense by delaying the animation start using `withDelay`.
48644864+### Reference
6395486563964866```typescript
63974867import { withDelay } from "react-native-reanimated"
6398486863994869function App() {
64004870 sv.value = withDelay(500, withTiming(0))
48714871+ // ...
64014872}
64024873```
6403487464046404-Final example:
48754875+#### Arguments
48764876+48774877+- **`delayMs`**: Specifies the duration (in milliseconds) before the animation begins.
48784878+48794879+- **`delayedAnimation`**: The animation that will be delayed.
48804880+48814881+- **`reduceMotion`** *(Optional)*: Determines how the animation responds to the device's reduced motion accessibility setting.
48824882+48834883+#### Returns
48844884+48854885+The `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`.
48864886+48874887+### Example
48884888+48894889+*(Example content would go here)*
48904890+48914891+### Platform Compatibility
48924892+48934893+|Android|iOS|Web|
48944894+|-|-|-|
48954895+|✅|✅|✅|
48964896+48974897+***
48984898+48994899+## useAnimatedSensor
49004900+49014901+`useAnimatedSensor` allows you to create animations based on device sensor data. It provides access to:
49024902+49034903+- **Accelerometer**: Measures device acceleration (excluding gravity) along the x, y, and z axes.
49044904+- **Gyroscope**: Captures the rotation rate of the device along the x, y, and z axes.
49054905+- **Gravity**: Provides the current gravity vector along the x, y, and z axes.
49064906+- **Magnetic Field**: Measures the Earth's magnetic field strength and direction in microtesla (μT).
49074907+- **Rotation**: Represents the device orientation using Euler angles and a quaternion.
49084908+49094909+For comprehensive documentation, refer to the Sensors guide on Android Developers and Device Motion in Apple Developer documentation.
49104910+49114911+### Reference
6405491264064913```typescript
64076407-const OFFSET = 40
64086408-const TIME = 250
64096409-const DELAY = 400
49144914+import { useAnimatedSensor, SensorType } from "react-native-reanimated"
49154915+49164916+function App() {
49174917+ const gyroscope = useAnimatedSensor(SensorType.GYROSCOPE)
6410491864116411-const handlePress = () => {
64126412- offset.value = withDelay(
64136413- DELAY,
64146414- withSequence(
64156415- // start from -OFFSET
64166416- withTiming(-OFFSET, { duration: TIME / 2 }),
64176417- // shake between -OFFSET and OFFSET 5 times
64186418- withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
64196419- // go back to 0 at the end
64206420- withTiming(0, { duration: TIME / 2 })
64216421- )
64226422- )
49194919+ useDerivedValue(() => {
49204920+ const { x, y, z } = gyroscope.sensor.value
49214921+ })
64234922}
64244923```
6425492464266426-### Summary
49254925+#### Arguments
6427492664286428-- **Modifiers**: `withRepeat`, `withSequence`, and `withDelay`.
64296429-- **`withRepeat`**: Repeats an animation a specified number of times or indefinitely.
64306430-- **`withSequence`**: Chains animations to run sequentially.
64316431-- **`withDelay`**: Delays the start of an animation.
49274927+##### `sensorType`
6432492864336433-### What's Next?
49294929+Specifies the sensor type using a `SensorType` enum:
6434493064356435-Explore handling `Tap` and `Pan` gestures, and learn about the `withDecay` animation function.
49314931+- `ACCELEROMETER`: Measures device acceleration in m/s².
49324932+- `GYROSCOPE`: Captures rotation rate in radians per second.
49334933+- `GRAVITY`: Provides gravity vector in m/s².
49344934+- `MAGNETIC_FIELD`: Measures magnetic field strength in microtesla (μT).
49354935+- `ROTATION`: Represents orientation using Euler angles and a quaternion.
6436493664376437-````markdown
64386438-# `useAnimatedScrollHandler`
49374937+##### `config` (Optional)
6439493864406440-The `useAnimatedScrollHandler` is a custom hook designed to provide an event handler for managing animated scrolling within React Native applications. This hook integrates seamlessly with various scrollable components, enabling developers to implement smooth and responsive animations.
49394939+|Name|Type|Default|Description|
49404940+|-|-|-|-|
49414941+|interval|`number \| "auto"`|`"auto"`|Time between sensor readings in milliseconds. `"auto"` matches the device's screen refresh rate.|
49424942+|adjustToInterfaceOrientation|`boolean`|`true`|Adjusts measurements to the current interface orientation.|
49434943+|iosReferenceFrame|`IOSReferenceFrame`|`IOSReferenceFrame.Auto`|Frame of reference for iOS sensors.|
6441494464426442-## Usage
49454945+Available `IOSReferenceFrame` options:
6443494664446444-To utilize the `useAnimatedScrollHandler`, you need to import it from its respective library or module where it's defined. Once imported, this hook can be invoked within a functional component to obtain an event handler reference that is specifically tailored for animated scroll events.
49474947+- `xArbitraryZVertical`: Z axis is vertical, X axis arbitrary in horizontal plane.
49484948+- `xArbitraryCorrectedZVertical`: Improved rotation accuracy with Z vertical and X arbitrary.
49494949+- `XMagneticNorthZVertical`: Z axis vertical, X points to magnetic north.
49504950+- `XTrueNorthZVertical`: Z axis vertical, X points to geographic north.
49514951+- `Auto`: Defaults based on device capabilities.
49524952+49534953+#### Returns
49544954+49554955+`useAnimatedSensor` returns an object:
49564956+49574957+|Name|Type|Description|
49584958+|-|-|-|
49594959+|sensor|`SharedValue<Value3D \| ValueRotation>`|Shared value with sensor measurements.|
49604960+|unregister|`() => void`|Stops listening to sensor updates when called.|
49614961+|isAvailable|`boolean`|Indicates if the sensor is available for use.|
49624962+|config|`SensorConfig`|Contains sensor configuration details.|
49634963+49644964+The shared value from the **rotation sensor** includes:
49654965+49664966+- Euler angles: `roll`, `pitch`, `yaw`.
49674967+- Quaternion components: `qw`, `qx`, `qy`, `qz`.
49684968+- Interface orientation.
49694969+49704970+Other sensors return measurements on x, y, z axes and interface orientation.
49714971+49724972+`InterfaceOrientation` enum values:
49734973+49744974+- `ROTATION_0`: Default rotation on Android, portrait on iOS.
49754975+- `ROTATION_90`: 90 degrees on Android, landscape right on iOS.
49764976+- `ROTATION_180`: 180 degrees on Android, upside down on iOS.
49774977+- `ROTATION_270`: 270 degrees on Android, landscape left on iOS.
6445497864464979### Example
6447498064486448-Below is a basic example demonstrating how to use `useAnimatedScrollHandler` in conjunction with a React Native ScrollView:
49814981+```typescript
49824982+export default function App() {
49834983+ const gravity = useAnimatedSensor(SensorType.GRAVITY);
49844984+49854985+ const animatedStyle = useAnimatedStyle(() => {
49864986+ return {
49874987+ transform: [
49884988+ { translateX: withSpring(gravity.sensor.value.x * 20) },
49894989+ { translateY: withSpring(gravity.sensor.value.y * 20) },
49904990+ ],
49914991+ };
49924992+ });
49934993+49944994+ return (
49954995+ <View style={styles.container}>
49964996+ <Animated.View style={[styles.box, animatedStyle]} />
49974997+ </View>
49984998+ );
49994999+}
50005000+```
50015001+50025002+### Remarks
50035003+50045004+- On iOS, enable location services (`Settings > Privacy > Location Services`) to read sensor data.
50055005+- On Web, ensure the device supports sensors and the application is served over HTTPS.
50065006+- Most sensors operate at resolutions up to 100Hz.
50075007+- Sensor data can be accessed on both UI and JavaScript threads.
50085008+50095009+### Platform Compatibility
50105010+50115011+|Android|iOS|Web|
50125012+|-|-|-|
50135013+|✅|✅|✅|
50145014+50155015+## dispatchCommand
50165016+50175017+The `dispatchCommand` function enables the execution of commands directly on a native component from the UI thread.
50185018+50195019+### Reference
6449502064505021```typescript
64516451-import { useAnimatedScrollHandler } from 'react-native-reanimated';
64526452-import { ScrollView, View, Text } from 'react-native';
50225022+import { dispatchCommand } from 'react-native-reanimated';
6453502364546454-const MyComponent = () => {
64556455- const scrollHandler = useAnimatedScrollHandler({
64566456- onScroll: (event) => {
64576457- // Handle the scroll event with animation logic here
64586458- console.log(event.contentOffset);
64596459- },
50245024+function App() {
50255025+ const animatedRef = useAnimatedRef();
50265026+50275027+ const gesture = Gesture.Tap().onStart(() => {
50285028+ dispatchCommand(animatedRef, 'focus');
64605029 });
6461503064625031 return (
64636463- <ScrollView
64646464- horizontal
64656465- pagingEnabled
64666466- showsHorizontalScrollIndicator={false}
64676467- onScroll={scrollHandler}
64686468- >
64696469- {/* Your content goes here */}
64706470- <View style={{ width: '100%', height: 200, backgroundColor: 'red' }} />
64716471- <View style={{ width: '100%', height: 200, backgroundColor: 'blue' }} />
64726472- <View style={{ width: '100%', height: 200, backgroundColor: 'green' }} />
64736473- </ScrollView>
50325032+ <>
50335033+ <AnimatedTextInput ref={animatedRef} style={styles.input} />
50345034+ <GestureDetector gesture={gesture}>
50355035+ <Button title="Focus" />
50365036+ </GestureDetector>
50375037+ </>
64745038 );
64756475-};
50395039+}
50405040+```
6476504164776477-export default MyComponent;
50425042+#### Arguments
50435043+50445044+- **`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.
50455045+50465046+- **`commandName`**: The name of the command to execute, such as `'focus'` or `'scrollToEnd'`.
50475047+50485048+- **`args` (Optional)**: An array of arguments for the command. Defaults to an empty array if not provided.
50495049+50505050+### Example
50515051+50525052+```typescript
50535053+const goDown = Gesture.Tap().onStart(() => {
50545054+ dispatchCommand(tosRef, "scrollToEnd", [true])
50555055+ dispatchCommand(loginRef, "focus")
50565056+})
64785057```
64796479-````
6480505864816481-In this example, `useAnimatedScrollHandler` is used to create a scroll handler that logs the current content offset whenever a scroll event occurs. This setup allows for enhanced control over scrolling animations within the component.
50595059+### Remarks
6482506064836483-### Parameters
50615061+- Commands vary depending on the component. Refer to the relevant React Native documentation for available commands specific to each component.
6484506264856485-The hook accepts an object with various properties that define how the scroll events should be handled:
50635063+### Platform Compatibility
6486506464876487-- **onScroll**: A function that receives the scroll event details, such as `contentOffset`, and can contain logic to animate or respond to the scroll action.
64886488-- Additional optional parameters may include `onBeginDrag`, `onActiveDrag`, `onEndDrag`, etc., depending on the specific requirements of your animation.
50655065+|Android|iOS|Web|
50665066+|-|-|-|
50675067+|✅|✅|❌|
6489506864906490-### Benefits
50695069+## setNativeProps
6491507064926492-Using `useAnimatedScrollHandler` offers several advantages:
50715071+The `setNativeProps` function allows for the imperative updating of component properties in React Native. It serves as an escape hatch intended for specific edge cases.
6493507264946494-- **Performance**: By leveraging React Native Reanimated, this hook ensures that animations are performed smoothly and efficiently.
64956495-- **Flexibility**: Developers can customize scroll behavior extensively through various event handlers.
64966496-- **Integration**: Seamlessly works with existing React Native components like ScrollView, FlatList, etc.
50735073+> **Caution:**\
50745074+> Prefer using `useAnimatedStyle` and `useAnimatedProps` when animating styles or properties, reserving `setNativeProps` for exceptional situations.
6497507564986498-By incorporating `useAnimatedScrollHandler` into your project, you can enhance the user experience with fluid and responsive scrolling animations.
50765076+### Reference
6499507765006500-````
50785078+```typescript
50795079+import { setNativeProps } from 'react-native-reanimated';
50805080+50815081+function App() {
50825082+ const animatedRef = useAnimatedRef();
50835083+50845084+ const tap = Gesture.Tap().onEnd(() => {
50855085+ setNativeProps(animatedRef, { text: '' });
50865086+ });
50875087+50885088+ return <TextInput ref={animatedRef} />;
50895089+}
50905090+```
50915091+50925092+#### Arguments
50935093+50945094+- **`animatedRef`:**\
50955095+ 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.
50965096+50975097+- **`updates`:**\
50985098+ An object containing properties that need updating, which can include both style properties (e.g., `width`, `backgroundColor`) and regular properties (e.g., `text`).
50995099+51005100+#### Returns
51015101+51025102+The function returns `undefined`.
51035103+51045104+### Remarks
51055105+51065106+- Prioritize using `useAnimatedStyle` and `useAnimatedProps` for animating styles or properties.
51075107+- Ensure that `setNativeProps` is used exclusively on the UI thread.
51085108+- 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.
51095109+51105110+### Platform Compatibility
51115111+51125112+|Android|iOS|Web|
51135113+|-|-|-|
51145114+|✅|✅|✅|
51155115+51165116+***
51175117+51185118+## React Native Reanimated: useReducedMotion Hook (Version 3.x)
6501511965026502-# Interpolation with `react-native-reanimated`
51205120+### Overview
6503512165046504-The `interpolate` function is used to map a numeric value from one specified range to another using linear interpolation.
51225122+The `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.
6505512365066506-## Reference Usage
51245124+### Reference
6507512565085126```typescript
65096509-import { interpolate, Extrapolation } from 'react-native-reanimated';
51275127+import { useReducedMotion } from "react-native-reanimated"
6510512865115129function App() {
65126512- const animatedStyle = useAnimatedStyle(() => ({
65136513- opacity: interpolate(sv.value, [0, 100], [0, 1], Extrapolation.CLAMP),
65146514- }));
51305130+ const reduceMotion = useReducedMotion()
51315131+51325132+ if (reduceMotion) {
51335133+ // Display static content ✨
51345134+ } else {
51355135+ // Run animations ✨
51365136+ }
51375137+51385138+ // Additional logic...
65155139}
65166516-````
51405140+```
6517514165186518-#### Parameters
51425142+#### Returns
6519514365206520-- **`value`**: A numeric value that will be mapped to the specified `output` range.
51445144+The `useReducedMotion` hook returns a boolean value indicating whether the reduced motion setting was enabled at the start of the app.
6521514565226522-- **`input`**: An array of numbers defining the input range for interpolation.
51465146+### Example Usage
6523514765246524-- **`output`**: An array of numbers defining the output range for interpolation, which should have at least as many points as the input range.
51485148+```typescript
51495149+import { useReducedMotion } from 'react-native-reanimated';
6525515065266526-- **`extrapolate` (Optional)**: Determines behavior when `value` is outside the `input` range. Defaults to `Extrapolation.EXTEND`.
51515151+function App() {
51525152+ const reduceMotion = useReducedMotion();
6527515365286528- Available options:
51545154+ if (reduceMotion) {
51555155+ return <StaticContent />;
51565156+ } else {
51575157+ return <AnimatedContent />;
51585158+ }
51595159+}
51605160+```
6529516165306530- - `Extrapolation.EXTEND`: Predicts values beyond the output range.
65316531- - `Extrapolation.CLAMP`: Clamps the value to the edge of the output range.
65326532- - `Extrapolation.IDENTITY`: Returns the provided value unchanged.
51625162+### Remarks
6533516365346534- String equivalents include `"extend"`, `"clamp"`, and `"identity"`.
51645164+- Changing the reduced motion setting does not trigger a component rerender.
51655165+- Unlike `AccessibilityInfo.isReduceMotionEnabled()`, `useReducedMotion` provides the value synchronously.
51665166+51675167+### Platform Compatibility
51685168+51695169+|Android|iOS|Web|
51705170+|-|-|-|
51715171+|✅|✅|✅|
51725172+51735173+This hook is compatible across Android, iOS, and Web platforms.
51745174+51755175+## makeMutable
51765176+51775177+**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).
6535517865366536- To apply extrapolation to a specific edge, use an object:
51795179+Internally, `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.
6537518065386538- ```typescript
65396539- const opacity = interpolate(sv.value, [0, 100], [0, 1], {
65406540- extrapolateLeft: Extrapolation.CLAMP,
65416541- })
65426542- ```
51815181+The object produced by `makeMutable` mirrors that returned by the `useSharedValue` hook, ensuring consistent usage thereafter.
6543518265446544-#### Return Value
51835183+### Reference
6545518465466546-The `interpolate` function returns a value mapped within the specified output range.
51855185+```typescript
51865186+import { makeMutable } from "react-native-reanimated"
51875187+51885188+const mv = makeMutable(100)
51895189+```
51905190+51915191+#### Arguments
51925192+51935193+##### `initial`
51945194+51955195+This 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.
51965196+51975197+#### Returns
51985198+51995199+`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.
52005200+52015201+### Example
52025202+52035203+### Remarks
52045204+52055205+**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.
52065206+52075207+- All remarks applicable to the `useSharedValue` hook are relevant to `makeMutable`.
52085208+- Avoid invoking `makeMutable` directly within component scope. Component re-renders will generate a new object, potentially resetting the initial value and losing previous state.
52095209+52105210+```typescript
52115211+function App() {
52125212+ const [counter, setCounter] = useState(0)
52135213+ const mv = makeMutable(counter) // 🚨 creates a new mutable value on each render
52145214+52155215+ useEffect(() => {
52165216+ const interval = setInterval(() => {
52175217+ setCounter((prev) => prev + 1) // updates the counter stored in component state
52185218+ }, 1000)
52195219+52205220+ return () => {
52215221+ clearInterval(interval)
52225222+ }
52235223+ }, [mv])
52245224+52255225+ useAnimatedReaction(
52265226+ () => mv.value,
52275227+ (value) => {
52285228+ console.log(value) // prints 0, 1, 2, ...
52295229+ }
52305230+ )
52315231+}
52325232+```
52335233+52345234+- 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.
52355235+52365236+```typescript
52375237+function App() {
52385238+ const mv = useMemo(() => makeMutable(0), [])
52395239+52405240+ useEffect(() => {
52415241+ mv.value = withRepeat(withSpring(100), -1, true) // creates an infinite animation
52425242+52435243+ return () => {
52445244+ cancelAnimation(mv) // ✅ stops the infinite animation on component unmount
52455245+ }
52465246+ }, [])
52475247+}
52485248+```
52495249+52505250+- `cancelAnimation` is not needed for non-animated values as they are automatically garbage collected when no references remain.
52515251+52525252+```typescript
52535253+const someFlag = makeMutable(false)
52545254+52555255+function App() {
52565256+ someFlag.value = true // ✅ no need to cancel the animation later on
52575257+}
52585258+```
52595259+52605260+- 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).
52615261+52625262+#### Comparison with `useSharedValue`
52635263+52645264+|Feature|`makeMutable`|`useSharedValue`|
52655265+|-|-|-|
52665266+|Object Creation|Creates a new object on each call|Reuses the same object on each call|
52675267+|Initial Value Change|A new object is created if `initial` changes|The initially created object remains unchanged if `initialValue` changes|
52685268+|Scope Usage|Can be used outside of component scope|Limited to use within component scope|
52695269+|Loop Usage|Usable in loops with variable iterations|Usable in loops only if the number of hooks (`useSharedValue` calls) is constant|
52705270+|Animation Cancellation|Does not automatically cancel animations on unmount|Automatically cancels animations when the component unmounts|
6547527165485272### Platform Compatibility
65495273···65515275|-|-|-|
65525276|✅|✅|✅|
6553527765546554-## Clamp Function in React Native Reanimated
52785278+## Accurate Call Stacks
52795279+52805280+When 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.
52815281+52825282+To 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.
52835283+52845284+### Reference
52855285+52865286+For 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.
52875287+52885288+```typescript
52895289+// metro.config.js
52905290+import { wrapWithReanimatedMetroConfig } from "react-native-reanimated/metro-config"
52915291+52925292+const config = {
52935293+ // Your existing Metro configuration options
52945294+}
52955295+52965296+export default wrapWithReanimatedMetroConfig(config)
52975297+```
52985298+52995299+### Example
53005300+53015301+The 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.
53025302+53035303+|Before|After|
53045304+|-|-|
53055305+|||
53065306+53075307+### Remarks
53085308+53095309+- `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**.
53105310+53115311+|Collapsed|Expanded|
53125312+|-|-|
53135313+|||
53145314+53155315+- 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.
53165316+53175317+## withClamp
6555531865566556-The `clamp` function is used to restrict a value within a specified range, ensuring it does not exceed the defined minimum and maximum bounds.
53195319+`withClamp` is an animation modifier that restricts the movement of your animation within a specified range. It's typically used in conjunction with `withSpring`.
6557532065585321### Reference
6559532265605323```typescript
65616561-import { clamp } from "react-native-reanimated"
53245324+import { withClamp } from "react-native-reanimated"
6562532565635326function App() {
65646564- const result = clamp(sv.value, 0, 100)
53275327+ sv.value = withClamp({ min: -1, max: 1 }, withSpring(0))
53285328+ // ...
65655329}
65665330```
6567533165685332#### Arguments
6569533365706570-- **`value`**: A numeric value that will be returned if it falls within the specified `min` and `max` range.
53345334+##### `config`
53355335+53365336+An object containing the following properties:
53375337+53385338+|Name|Type|Description|
53395339+|-|-|-|
53405340+|min|number|Optional. The lowest value your animation can reach.|
53415341+|max|number|Optional. The highest value your animation can reach.|
6571534265726572-- **`min`**: The lower bound. If the provided `value` is less than this number, `min` will be returned.
53435343+##### `animation`
53445344+53455345+The spring animation you wish to clamp.
6573534665746574-- **`max`**: The upper bound. If the provided `value` exceeds this number, `max` will be returned.
53475347+```typescript
53485348+const clampedStyleWithDelay = useAnimatedStyle(() => {
53495349+ return {
53505350+ width: withClamp({ min: 0, max: 100 }, withSpring(randomWidth.value)),
53515351+ }
53525352+})
53535353+```
6575535465765355#### Returns
6577535665786578-The function returns a numeric value that lies between the specified `min` and `max` bounds.
53575357+`withClamp` returns an animation object. This can be directly assigned to a shared value or used as a style value in `useAnimatedStyle`.
53585358+53595359+|Platform|Supported|
53605360+|-|-|
53615361+|Android|✅|
53625362+|iOS|✅|
53635363+|Web|✅|
53645364+53655365+## Logger configuration
53665366+53675367+Reanimated 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.
53685368+53695369+By default, the logger configuration requires no setup and displays all warnings and errors. To customize this behavior, use the `configureReanimatedLogger` function.
53705370+53715371+### Reference
53725372+53735373+To alter the default Reanimated logger settings, import `configureReanimatedLogger` from `react-native-reanimated` and invoke it with your desired configuration:
53745374+53755375+```typescript
53765376+import {
53775377+ configureReanimatedLogger,
53785378+ ReanimatedLogLevel,
53795379+} from "react-native-reanimated"
53805380+53815381+// Default configuration example
53825382+configureReanimatedLogger({
53835383+ level: ReanimatedLogLevel.warn,
53845384+ strict: true, // Strict mode is enabled by default
53855385+})
53865386+```
53875387+53885388+#### Configuration Options
53895389+53905390+- **`level`:** Specifies the minimum log level to display using a value from `ReanimatedLogLevel`.
53915391+53925392+- **`strict`:** A boolean that toggles strict mode. Enabling it results in additional warnings to help identify potential code issues.
53935393+53945394+### Remarks
53955395+53965396+- The logger configuration is global, affecting all Reanimated warnings and errors. It cannot be configured on a per-file or per-component basis.
53975397+53985398+- Call `configureReanimatedLogger` before creating any Reanimated animations, typically in the root file of your application.
6579539965806580-### Example Usage
54005400+- 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.
54015401+54025402+### Platform Compatibility
54035403+54045404+|Android|iOS|Web|
54055405+|-|-|-|
54065406+|✅|✅|✅|
54075407+54085408+## React Native Reanimated: ReducedMotionConfig
54095409+54105410+**Version:** 3.x
54115411+54125412+### Overview
54135413+54145414+The `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.
54155415+54165416+> **Caution:** The new configuration will be applied globally across the entire application.
54175417+54185418+### Reference
6581541965825420```typescript
65836583-import { clamp } from "react-native-reanimated"
54215421+import { ReducedMotionConfig, ReduceMotion } from 'react-native-reanimated';
6584542265855423function App() {
65866586- const constrainedValue = clamp(150, 0, 100) // Result will be 100
54245424+ return (
54255425+ // ...
54265426+ <ReducedMotionConfig mode={ReduceMotion.Never} />
54275427+ // ...
54285428+ );
65875429}
65885430```
6589543154325432+#### Arguments
54335433+54345434+##### `mode`
54355435+54365436+This parameter determines how animations should respond to the device's reduced motion accessibility setting:
54375437+54385438+- **`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.
54395439+54405440+- **`ReduceMotion.Always`:** Consistently disables animations, regardless of the device's accessibility configuration.
54415441+54425442+- **`ReduceMotion.Never`:** Ensures that animations remain enabled at all times.
54435443+65905444### Platform Compatibility
6591544565925446|Android|iOS|Web|
65935447|-|-|-|
65945448|✅|✅|✅|
6595544965966596-This function is compatible across Android, iOS, and Web platforms.
54505450+- Reference
54515451+ - Arguments
54525452+- Example
54535453+- Platform compatibility
54545454+54555455+## Worklets
6597545665986598-## interpolateColor Function
54575457+Worklets are short-running JavaScript functions that execute on the UI thread, enabling efficient style calculations and event reactions. Reanimated leverages worklets for these tasks.
6599545866006600-The `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.
54595459+### Creating Worklets
6601546066026602-### Reference Example
54615461+To define a custom worklet, use the `'worklet';` directive at the start of your function:
6603546266045463```typescript
66056605-import { interpolateColor } from 'react-native-reanimated';
54645464+function myWorklet() {
54655465+ "worklet"
54665466+ console.log("Hello from a worklet")
54675467+}
54685468+```
54695469+54705470+The 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.
54715471+54725472+### Automatic Workletization
54735473+54745474+When using Reanimated and Gesture Handler, code is typically automatically workletized and executed on the UI thread:
54755475+54765476+```typescript
54775477+import { useAnimatedStyle } from "react-native-reanimated"
6606547866075479function App() {
66086608- const progress = useSharedValue(0);
54805480+ const style = useAnimatedStyle(() => {
54815481+ // Executed on the UI thread
54825482+ return { opacity: 0.5 }
54835483+ })
54845484+}
54855485+```
54865486+54875487+### Manual Worklet Execution
54885488+54895489+To manually schedule worklet execution, use `runOnUI`:
6609549066106610- const animatedStyle = useAnimatedStyle(() => {
66116611- return {
66126612- backgroundColor: interpolateColor(
66136613- progress.value,
66146614- [0, 1],
66156615- ['red', 'green']
66166616- ),
66176617- };
66186618- });
54915491+```typescript
54925492+function myWorklet() {
54935493+ "worklet"
54945494+ console.log("Hello from the UI thread")
54955495+}
6619549654975497+function onPress() {
54985498+ runOnUI(myWorklet)()
54995499+}
55005500+```
55015501+55025502+Arguments can be passed to worklets as follows:
55035503+55045504+```typescript
55055505+function myWorklet(greeting: string) {
55065506+ "worklet"
55075507+ console.log(`${greeting} from the UI thread`)
55085508+}
55095509+55105510+function onPress() {
55115511+ runOnUI(myWorklet)("Howdy")
55125512+}
55135513+```
55145514+55155515+### Worklet Closures
55165516+55175517+Worklets are closures, allowing them to access variables declared outside their scope. Only referenced variables are captured:
55185518+55195519+```typescript
55205520+const width = 135.5
55215521+55225522+function otherWorklet() {
55235523+ "worklet"
55245524+ console.log("Captured width is", width)
55255525+}
55265526+```
55275527+55285528+Avoid capturing large objects within worklets to prevent performance issues:
55295529+55305530+```typescript
55315531+const theme = {...}; // Large object
55325532+55335533+function myWorklet() {
55345534+ 'worklet';
55355535+ console.log(theme.color); // 🚨 Captures entire `theme` object
55365536+}
55375537+```
55385538+55395539+To mitigate this, assign the needed property to a separate variable:
55405540+55415541+```typescript
55425542+const theme = {...};
55435543+const color = theme.color;
55445544+55455545+function myWorklet() {
55465546+ 'worklet';
55475547+ console.log(color); // ✅ Captures only `color`
55485548+}
55495549+```
55505550+55515551+### Returning Data
55525552+55535553+Worklets can return data within the same thread:
55545554+55555555+```typescript
55565556+function returningWorklet() {
55575557+ "worklet"
55585558+ return "I'm back" // On the UI thread
55595559+}
55605560+55615561+function someWorklet() {
55625562+ "worklet"
55635563+ const what = returningWorklet() // Still on the UI thread
55645564+ console.log("On the UI thread, other worklet says", what)
55655565+}
55665566+```
55675567+55685568+### Data Sharing Between Threads
55695569+55705570+Use shared values to pass data between the UI and JS threads:
55715571+55725572+```typescript
55735573+import { useSharedValue } from "react-native-reanimated"
55745574+55755575+function App() {
55765576+ const width = useSharedValue(100)
55775577+55785578+ function myWorklet() {
55795579+ "worklet"
55805580+ width.value += 50
55815581+ }
55825582+55835583+ useEffect(() => {
55845584+ console.log(width.value) // Accessible on both JS and UI threads
55855585+ }, [])
55865586+}
55875587+```
55885588+55895589+### Running Functions on the JS Thread
55905590+55915591+Use `runOnJS` to execute functions from the UI thread, often for non-worklet functions or React state updates:
55925592+55935593+```typescript
55945594+import { router } from "expo-router"
55955595+import { Gesture } from "react-native-gesture-handler"
55965596+55975597+function App() {
55985598+ const tap = Gesture.Tap().onEnd(() => {
55995599+ // Worklet context
56005600+ runOnJS(router.back)()
56015601+ })
56025602+}
56035603+```
56045604+56055605+Ensure functions passed to `runOnJS` are defined in the JavaScript thread scope:
56065606+56075607+```typescript
56085608+function App() {
56095609+ const tap = Gesture.Tap().onEnd(() => {
56105610+ // myFunction is defined on the UI thread 🚨
56115611+ const myFunction = () => {}
56125612+ runOnJS(myFunction)() // 💥 Error
56135613+ })
56145614+}
56155615+```
56165616+56175617+### Custom Worklet Runtimes
56185618+56195619+Worklets can operate in custom runtimes beyond Reanimated's default. Libraries like VisionCamera and LiveMarkdown create their own worklet environments.
56205620+56215621+Create your own worklet runtime using `createWorkletRuntime`.
56225622+56235623+## Accessibility
56245624+56255625+This 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.
56265626+56275627+The 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:
56285628+56295629+- `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.
56305630+- `ReduceMotion.Always`: Consistently disables the animation, regardless of the device's accessibility configuration.
56315631+- `ReduceMotion.Never`: Ensures that the animation remains enabled at all times.
56325632+56335633+By default, all animations are configured with `ReduceMotion.System`.
56345634+56355635+### Reduced Motion in Animations
56365636+56375637+```typescript
56385638+import { withDelay, withTiming } from "react-native-reanimated"
56395639+56405640+function App() {
56415641+ sv1.value = withTiming(0, { reduceMotion: ReduceMotion.System })
56425642+ sv2.value = withDelay(
56435643+ 1000,
56445644+ withTiming(toValue, { duration }),
56455645+ ReduceMotion.System
56465646+ )
66205647 // ...
56485648+}
56495649+```
56505650+56515651+When reduced motion is enabled:
56525652+56535653+- `withSpring` and `withTiming` return the `toValue` immediately.
56545654+- `withDecay` returns the current value immediately, considering the clamp parameter.
56555655+- `withDelay` initiates the next animation immediately.
56565656+- `withRepeat`:
56575657+ - If `numberOfReps` is infinite or even and the animation is reversed, then the repeated animation does not start.
56585658+ - Otherwise, the repeated animation runs once.
56595659+- `withSequence` exclusively starts animations that have reduced motion disabled.
56605660+56615661+Higher-order animations pass the configuration to their children only if the children haven't been configured by the user. For example:
6621566266226622- return <Animated.View style={[{ width: 100, height: 100 }, animatedStyle]} />;
56635663+This animation will instantaneously reach the `toValue`:
56645664+56655665+```typescript
56665666+import { withDelay, withTiming } from "react-native-reanimated"
56675667+56685668+function App() {
56695669+ sv.value = withDelay(
56705670+ 1000,
56715671+ withTiming(toValue, { duration }),
56725672+ ReduceMotion.Always
56735673+ )
56745674+ // ...
56755675+}
56765676+```
56775677+56785678+This animation will execute as usual even if reduced motion is enabled on the device:
56795679+56805680+```typescript
56815681+import { withDelay, withTiming } from "react-native-reanimated"
56825682+56835683+function App() {
56845684+ sv.value = withDelay(
56855685+ 1000,
56865686+ withTiming(toValue, { duration }),
56875687+ ReduceMotion.Never
56885688+ )
56895689+ // ...
56905690+}
56915691+```
56925692+56935693+And here `withTiming` will be executed as usual and without delay:
56945694+56955695+```typescript
56965696+import { withDelay, withTiming } from "react-native-reanimated"
56975697+56985698+function App() {
56995699+ sv.value = withDelay(
57005700+ 1000,
57015701+ withTiming(toValue, { duration, reduceMotion: ReduceMotion.Never }),
57025702+ ReduceMotion.Always
57035703+ )
57045704+ // ...
57055705+}
57065706+```
57075707+57085708+### Reduced Motion in Layout Animations
57095709+57105710+```typescript
57115711+import { BounceIn } from "react-native-reanimated"
57125712+57135713+function App() {
57145714+ const entering = BounceIn.reduceMotion(ReduceMotion.System)
57155715+ // ...
57165716+}
57175717+```
57185718+57195719+When reduced motion is enabled:
57205720+57215721+- Entering, keyframe, and layout animations instantaneously reach their endpoints.
57225722+- Exiting animations and shared transitions are omitted.
57235723+57245724+### `useReducedMotion`
57255725+57265726+This 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.
57275727+57285728+```typescript
57295729+import { BounceIn } from "react-native-reanimated"
57305730+57315731+function App() {
57325732+ const reduceMotion = useReducedMotion()
57335733+ const entering = reduceMotion
57345734+ ? FadeIn.reduceMotion(ReduceMotion.Never)
57355735+ : BounceIn
57365736+ // ...
57375737+}
57385738+```
57395739+57405740+## Glossary of terms
57415741+57425742+### Animated Component
57435743+57445744+Animated components are those that can be animated using Reanimated. The library includes built-in components such as `Animated.View`, `Animated.Text`, and `Animated.ScrollView`.
57455745+57465746+```typescript
57475747+import Animated from 'react-native-reanimated';
57485748+57495749+function App() {
57505750+ return (
57515751+ <Animated.View
57525752+ style={{
57535753+ width: 100,
57545754+ height: 100,
57555755+ backgroundColor: 'violet',
57565756+ }}
57575757+ />
57585758+ );
57595759+}
57605760+```
57615761+57625762+For components not included in Reanimated, you can make their props and styles animatable by wrapping them with `createAnimatedComponent`:
57635763+57645764+```typescript
57655765+import Animated from "react-native-reanimated"
57665766+import { Circle } from "react-native-svg"
57675767+57685768+const AnimatedCircle = Animated.createAnimatedComponent(Circle)
57695769+```
57705770+57715771+### Shared Value
57725772+57735773+Shared values are essential for animations in Reanimated. They are defined using the `useSharedValue` hook and accessed or modified via their `.value` property.
57745774+57755775+```typescript
57765776+import { useSharedValue } from "react-native-reanimated"
57775777+57785778+function App() {
57795779+ const sv = useSharedValue(0)
57805780+57815781+ const handlePress = () => {
57825782+ sv.value += 10
57835783+ }
57845784+57855785+ // rest of your glamorous code ✨
57865786+}
57875787+```
57885788+57895789+Shared values can store any type and automatically synchronize data between the JavaScript thread and the UI thread.
57905790+57915791+### Animatable Value
57925792+57935793+An 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.
57945794+57955795+### Animation Function
57965796+57975797+Animation functions define how animations should behave. Reanimated provides three built-in animation functions:
57985798+57995799+- `withSpring`: Creates spring-based animations.
58005800+- `withTiming`: Creates duration and easing-based animations.
58015801+- `withDecay`: Mimics motion with a given deceleration rate.
58025802+58035803+These can be combined with modifiers for complex animations.
58045804+58055805+### Animation Modifier
58065806+58075807+Animation modifiers customize animations. Known as higher-order animations, Reanimated includes:
58085808+58095809+- `withDelay`: Adds a delay before the animation starts.
58105810+- `withRepeat`: Repeats an animation a specified number of times.
58115811+- `withSequence`: Chains animations sequentially.
58125812+- `withClamp`: Limits animation boundaries to a specific range.
58135813+58145814+### Animation Object
58155815+58165816+An 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.
58175817+58185818+When passed to a shared value, it is treated as an animatable value:
58195819+58205820+```typescript
58215821+sv.value = withSpring(100)
58225822+```
58235823+58245824+### Animations in Inline Styling
58255825+58265826+Shared values can be directly used in the `style` property without `useAnimatedStyle`.
58275827+58285828+Example:
58295829+58305830+```typescript
58315831+function App() {
58325832+ const width = useSharedValue(100);
58335833+58345834+ return <Animated.View style={{ width }} />;
58355835+}
58365836+```
58375837+58385838+### Layout Animation Modifier
58395839+58405840+Layout animation modifiers customize layout animations. Example usage:
58415841+58425842+```typescript
58435843+<Animated.View entering={FadeOutLeft.duration(500).easing(Easing.ease)} />
58445844+```
58455845+58465846+Built-in modifiers include:
58475847+58485848+- `.duration(durationMs: number)`: Sets the animation length in milliseconds.
58495849+- `.easing(easingFunction: EasingFunction)`: Defines the animation curve.
58505850+- `.springify()`: Enables spring-based animations.
58515851+- `.damping(value: number)`: Controls how quickly a spring stops moving.
58525852+- `.withCallback(callback: (finished: boolean) => void)`: Triggers after the animation ends.
58535853+58545854+### Worklet
58555855+58565856+Worklets are short-running JavaScript functions executed on the UI thread. They can also run on the JavaScript thread like regular functions.
58575857+58585858+Code is often automatically workletized and runs on the UI thread by default:
58595859+58605860+```typescript
58615861+const style = useAnimatedStyle(() => {
58625862+ console.log("Running on the UI thread")
58635863+ return { opacity: 0.5 }
58645864+})
58655865+```
58665866+58675867+Custom worklets can be created using the `"worklet";` directive:
58685868+58695869+```typescript
58705870+function myWorklet() {
58715871+ "worklet"
58725872+ console.log("Running on the UI thread")
66235873}
66245874```
6625587566266626-#### Arguments
58765876+Use `runOnUI` to manually execute worklets on the UI thread:
58775877+58785878+```typescript
58795879+function myWorklet(greeting) {
58805880+ "worklet"
58815881+ console.log(`${greeting} from the UI thread`)
58825882+}
58835883+58845884+function onPress() {
58855885+ runOnUI(myWorklet)("Howdy")
58865886+}
58875887+```
58885888+58895889+### To Workletize
58905890+58915891+Converts 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.
58925892+58935893+### JavaScript Thread
58945894+58955895+The JavaScript thread handles code execution in the app, serving as the primary location for React Native app code execution.
58965896+58975897+### UI Thread
58985898+58995899+The 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.
59005900+59015901+### Reanimated Babel Plugin
59025902+59035903+This plugin automatically workletizes certain functions used with Reanimated, reducing boilerplate code. Details are available in the Reanimated Babel plugin README.
59045904+59055905+## Entering/Exiting animations
59065906+59075907+The 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:
59085908+59095909+#### Overview
59105910+59115911+- **Library**: `react-native-reanimated`
59125912+- **Purpose**: To create smooth, performant animations on Android, iOS, and Web platforms.
59135913+- **Animations Covered**:
59145914+ - Pinch
59155915+ - Pinch Zoom
59165916+ - Pinch Rotate
59175917+ - Pinch Scale
59185918+ - Pinch Translate
59195919+ - Pinch X
59205920+ - Pinch Y
59215921+ - PinchXY
59225922+ - PinchZoomRotate
59235923+ - PinchZoomScale
59245924+ - PinchZoomTranslate
59255925+ - PinchZoomX
59265926+ - PinchZoomY
59275927+ - PinchZoomXY
59285928+ - PinchZoomRotateScale
59295929+ - PinchZoomRotateTranslate
59305930+ - PinchZoomRotateX
59315931+ - PinchZoomRotateY
59325932+ - PinchZoomRotateXY
59335933+ - PinchZoomScaleTranslate
59345934+ - PinchZoomScaleX
59355935+ - PinchZoomScaleY
59365936+ - PinchZoomScaleXY
59375937+ - PinchZoomTranslateX
59385938+ - PinchZoomTranslateY
59395939+ - PinchZoomTranslateXY
59405940+ - PinchZoomRotateScaleTranslate
59415941+ - PinchZoomRotateScaleX
59425942+ - PinchZoomRotateScaleY
59435943+ - PinchZoomRotateScaleXY
59445944+ - PinchZoomRotateTranslateX
59455945+ - PinchZoomRotateTranslateY
59465946+ - PinchZoomRotateTranslateXY
59475947+ - PinchZoomScaleTranslateX
59485948+ - PinchZoomScaleTranslateY
59495949+ - PinchZoomScaleTranslateXY
59505950+ - PinchZoomRotateScaleTranslateX
59515951+ - PinchZoomRotateScaleTranslateY
59525952+ - PinchZoomRotateScaleTranslateXY
59535953+ - Other animations like Bounce, Fade, Flip, etc.
6627595466286628-- **`value`**: A number from the input range that is mapped to the output range.
59555955+#### Animation Configuration
6629595666306630-- **`input`**: An array of numbers specifying the input range for interpolation. The values should be in increasing order.
59575957+##### Time-based Modifiers
6631595866326632-- **`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.
59595959+- **Function**: `withTiming`
59605960+- **Customization**:
59615961+ - `.easing(easingFunction: EasingFunction)`: Defines the animation curve. Default is `Easing.inOut(Easing.quad)`.
59625962+ - Note: These modifiers do not affect spring animations.
6633596366346634-- **`colorSpace`** *(Optional)*: Specifies the color space for interpolation, either `'HSV'` or `'RGB'`. Defaults to `'RGB'`.
59645964+##### Spring-based Modifiers
6635596566366636-- **`options`** *(Optional)*: Additional parameters for color interpolation:
59665966+- **Function**: `withSpring`
59675967+- **Customization**:
59685968+ - `.springify()`: Enables spring-based configuration.
59695969+ - `.damping(value: number)`: Controls how quickly the spring stops. Default is `10`.
59705970+ - `.mass(value: number)`: Represents the weight of the spring. Lower values make animations faster. Default is `1`.
59715971+ - `.stiffness(value: number)`: Determines bounciness. Default is `100`.
59725972+ - `.overshootClamping(value: boolean)`: Prevents bouncing over the target position. Default is `false`.
59735973+ - `.restDisplacementThreshold(value: number)`: Displacement threshold for snapping to the final position without oscillations. Default is `0.001`.
59745974+ - `.restSpeedThreshold(value: number)`: Speed threshold for snapping to the final position without oscillations. Default is `2`.
59755975+59765976+##### Common Modifiers
59775977+59785978+- **Customization**:
59795979+ - `.duration(durationMs: number)`: Length of the animation in milliseconds. Default is `300`.
59805980+ - `.delay(durationMs: number)`: Delay before starting the animation. Default is `0`.
59815981+ - `.randomDelay()`: Randomizes delay between `0` and provided value, defaulting to `1000ms` if not specified.
59825982+ - `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts animation based on device's reduced motion settings.
59835983+ - `.withInitialValues(values: StyleProps)`: Overrides initial configuration of the animation.
59845984+ - `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
6637598566386638- |Options|Type|Default|Description|
66396639- |-|-|-|-|
66406640- |`gamma`|`number`|2.2|Gamma parameter used in gamma correction.|
66416641- |`useCorrectedHSVInterpolation`|`boolean`|true|Reduces the number of hues during interpolation by treating HSV as circular.|
59865986+#### Platform Compatibility
6642598766436643-#### Options Explanation
59885988+- **Android**: Supported
59895989+- **iOS**: Supported
59905990+- **Web**: Supported
6644599166456645-- **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.
59925992+This guide provides developers with the tools to create and customize animations effectively across multiple platforms using `react-native-reanimated`.
6646599366476647-- **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).
59945994+## Troubleshooting React Native Reanimated Build Issues on Windows
59955995+59965996+This 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:
59975997+59985998+- `Execution failed for task ':react-native-reanimated:buildCMakeDebug[x86_64]'`
59995999+- `Execution failed for task ':react-native-reanimated:buildCMakeRelWithDebInfo[arm64-v8a]'`
60006000+- `Task :react-native-reanimated:buildCMakeDebug[x86_64] FAILED`
60016001+- `C/C++: ninja: error: mkdir(...): No such file or directory`
60026002+- `C++ build system [build] failed while executing`
60036003+- `Picked up _JAVA_OPTIONS`
60046004+60056005+### What Not to Do
60066006+60076007+If you encounter any of the above errors, avoid these actions:
60086008+60096009+#### ❌ Avoid Disabling New Architecture
60106010+60116011+Starting 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.
60126012+60136013+#### ❌ Avoid Downgrading Android Gradle Plugin (AGP)
60146014+60156015+Do not modify the AGP version in `gradle.properties`. Use the version specified in the official app template to prevent version conflicts and unsupported features.
60166016+60176017+#### ❌ Avoid Downgrading Reanimated or Other Dependencies
60186018+60196019+Downgrading 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.
60206020+60216021+#### ❌ Avoid Posting Duplicate "Same Issue" Comments
60226022+60236023+Before 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.
60246024+60256025+### Recommended Actions
60266026+60276027+#### ✅ Ensure Correct Environment Setup
60286028+60296029+Follow 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.
60306030+60316031+#### ✅ Use Compatible Reanimated Version
60326032+60336033+Use the latest supported version of Reanimated based on your app setup:
60346034+60356035+- **Expo SDK**: Match major and minor versions with Expo SDK.
60366036+ - Example: Expo SDK 52 supports `~3.16.x`. Update to the latest patch, e.g., `3.16.7`.
60376037+60386038+|Expo SDK Version|Reanimated Version|
60396039+|-|-|
60406040+|`52`|`~3.16.1`|
60416041+|`51`|`~3.10.1`|
60426042+|`50`|`~3.6.2`|
60436043+60446044+- **Expo Prebuild or React Native without Framework**: Use a version compatible with your React Native version according to the Compatibility table.
60456045+60466046+#### ✅ Use Appropriate CMake Version
60476047+60486048+Ensure 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`.
60496049+60506050+#### ✅ Use Appropriate Ninja Version
60516051+60526052+Use Ninja `1.12.0` or newer (latest is `1.12.1`) as older versions may not handle long paths correctly.
60536053+60546054+#### ✅ Use Compatible Android NDK Version
60556055+60566056+Match the NDK version with that used in the official app template. It should be installed automatically during app build.
60576057+60586058+#### ✅ Unset `_JAVA_OPTIONS`
60596059+60606060+Unsetting this environment variable can resolve certain errors and allow builds to pass.
60616061+60626062+#### ✅ Enable Long Paths Support in Windows Registry
60636063+60646064+Follow instructions to enable long paths support on Windows.
60656065+60666066+#### ✅ Avoid Whitespace in Project Path
60676067+60686068+Paths with spaces may cause issues. Move projects to directories without whitespace, e.g., `D:\Mobile Apps\MyAwesomeProject`.
60696069+60706070+#### ✅ Ensure Short Project Path
60716071+60726072+Avoid paths longer than 240 characters. Move or clone the project to a shorter path, e.g., `D:\AwesomeProject`.
60736073+60746074+#### ✅ Remove or Invalidate Caches
60756075+60766076+Clear compilation artifacts in directories like:
60776077+60786078+- `android\build`
60796079+- `android\.cxx`
60806080+- `android\.gradle`
60816081+- `node_modules\react-native-reanimated\android\build`
60826082+60836083+Invalidate Android Studio caches (File → Invalidate Caches…).
60846084+60856085+#### ⚠️ Persistent Issues
60866086+60876087+If problems persist after following these steps, submit an issue in the repository with full build logs and a minimal reproducible example.
60886088+60896089+## Compatibility Table
60906090+60916091+### Currently Supported React Native Versions (Paper)
60926092+60936093+|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|
60946094+|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
60956095+|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
60966096+|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
60976097+|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
60986098+|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
60996099+|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
61006100+|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
61016101+|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
61026102+|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
61036103+|3.6.x – 3.8.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|
61046104+|3.5.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
61056105+|3.3.x – 3.4.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
61066106+|3.0.x – 3.2.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
61076107+|2.14.x – 2.17.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
61086108+|2.11.x – 2.13.x|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|
61096109+|2.10.x|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|
61106110+|2.5.x – 2.9.x|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|
61116111+|2.3.x – 2.4.x|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|no|
61126112+61136113+**Note:** Reanimated 2 will not receive support for the newest React Native versions. To access the latest features and updates, upgrade to Reanimated 3.
61146114+61156115+### Supported React Native Versions on the New Architecture (Fabric)
61166116+61176117+To 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.
61186118+61196119+Reanimated supports bridgeless mode.
61206120+61216121+|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|
61226122+|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
61236123+|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
61246124+|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
61256125+|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
61266126+|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
61276127+|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
61286128+|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
61296129+|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
61306130+|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
61316131+|3.6.x – 3.8.x|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|no|no|
61326132+|3.1.x – 3.5.x|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|
61336133+|3.0.x|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|no|
61346134+61356135+## useSharedValue
61366136+61376137+`useSharedValue` is a hook that allows you to define shared values within your components.
61386138+61396139+### Reference
61406140+61416141+```typescript
61426142+import { useSharedValue } from "react-native-reanimated"
61436143+61446144+function App() {
61456145+ const sv = useSharedValue(100)
61466146+61476147+ // Accessing the shared value
61486148+ console.log(sv.value)
61496149+61506150+ // Modifying the shared value
61516151+ sv.value += 50
61526152+}
61536153+```
61546154+61556155+#### Arguments
61566156+61576157+##### `initialValue`
61586158+61596159+The 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`.
6648616066496161#### Returns
6650616266516651-The function returns an interpolated color in `rgba(r, g, b, a)` format within the specified output range.
61636163+`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.
61646164+61656165+##### React Compiler Support
61666166+61676167+When 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.
61686168+61696169+```typescript
61706170+function App() {
61716171+ const sv = useSharedValue(100)
61726172+61736173+ const animatedStyle = useAnimatedStyle(() => {
61746174+ "worklet"
61756175+ return { width: sv.get() * 100 }
61766176+ })
61776177+61786178+ const handlePress = () => {
61796179+ sv.set((value) => value + 1)
61806180+ }
61816181+}
61826182+```
6652618366536184### Remarks
6654618566556655-- The function operates similarly to the `interpolate` function but specifically outputs a color string in `rgba(r, g, b, a)` notation.
61866186+- 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.
61876187+61886188+- 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.
61896189+61906190+- 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.
61916191+61926192+- 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.
61936193+61946194+```typescript
61956195+function App() {
61966196+ const sv = useSharedValue(100) // initially set to 100
61976197+61986198+ sv.value += 50 // modifying the shared value
61996199+62006200+ console.log(sv.value) // logs 100 due to asynchronous update on JS thread
62016201+}
62026202+```
62036203+62046204+- Avoid destructuring assignment with shared values. While valid in JavaScript, it prevents Reanimated from maintaining reactivity.
62056205+62066206+```typescript
62076207+function App() {
62086208+ let { value } = sv // avoid this pattern
62096209+62106210+ console.log(value) // reading is fine
62116211+62126212+ value += 50 // does not update styles
62136213+}
62146214+```
62156215+62166216+- When storing objects in a shared value, ensure to reassign the entire object rather than modifying its properties individually.
62176217+62186218+```typescript
62196219+function App() {
62206220+ const sv = useSharedValue({ x: 0, y: 0 })
62216221+62226222+ sv.value.x = 50 // loses reactivity
62236223+62246224+ sv.value = { x: 50, y: 0 } // correct approach
62256225+}
62266226+```
62276227+62286228+- For large arrays or complex objects in a shared value, use the `.modify` method to alter the existing value without creating a new one.
62296229+62306230+```typescript
62316231+function App() {
62326232+ const sv = useSharedValue([1, 2, 3])
62336233+62346234+ sv.value.push(1000) // loses reactivity
62356235+62366236+ sv.value = [...sv.value, 1000] // creates a new copy
62376237+62386238+ sv.modify((value) => {
62396239+ "worklet"
62406240+ value.push(1000) // correct approach
62416241+ return value
62426242+ })
62436243+}
62446244+```
6656624566576246### Platform Compatibility
66586247···66606249|-|-|-|
66616250|✅|✅|✅|
6662625166636663-This function is versatile and compatible across major platforms, making it ideal for cross-platform applications.
62526252+## Contributing
62536253+62546254+Thank you for considering contributing to Reanimated. Contributions can range from triaging issues and enhancing documentation to reviewing Pull Requests and submitting code changes.
62556255+62566256+### Ways to Contribute
62576257+62586258+1. **Handling Open Issues**: Assist by providing detailed descriptions and reproducible examples for existing issues, which helps other contributors understand and address them more efficiently.
62596259+62606260+1. **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.
62616261+62626262+1. **Reviewing Pull Requests**: Review submitted Pull Requests to identify potential issues or bugs that may have been overlooked, ensuring high-quality contributions.
62636263+62646264+1. **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.
62656265+62666266+#### Repository Structure
62676267+62686268+The Reanimated repository is organized as follows:
62696269+62706270+```
62716271+├── apps
62726272+│ ├── common-app // Shared source for example apps
62736273+│ ├── paper-example // React Native app using Old Architecture
62746274+│ ├── fabric-example // React Native app using New Architecture
62756275+│ ├── macos-example // React Native for MacOS wrapper
62766276+│ ├── next-example // Next.js wrapper
62776277+│ ├── tvos-example // React Native for TVOS wrapper
62786278+│ └── web-example // React Native for Web wrapper
62796279+└── packages
62806280+ ├── docs-reanimated // Documentation source
62816281+ ├── eslint-plugin-reanimated // ESLint plugin source
62826282+ └── react-native-reanimated
62836283+ ├── android // Android native code
62846284+ ├── apple // iOS native code
62856285+ ├── Common // Shared C++ code
62866286+ ├── scripts // CI pipeline scripts
62876287+ ├── src // Reanimated JS source
62886288+ └── plugin // Babel plugin source
62896289+```
62906290+62916291+### Handling Open Issues
62926292+62936293+Providing detailed descriptions and reproducible examples for issues can significantly aid other contributors. Ensure that issues include:
62946294+62956295+- A cloneable repository.
62966296+- Clear reproduction steps.
62976297+- Comprehensive descriptions.
62986298+- Relevant stack traces.
62996299+63006300+If these details are missing, consider asking the issue owner or providing them yourself to facilitate quicker resolutions.
63016301+63026302+### Documentation Assistance
63036303+63046304+Improving 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:
63056305+63066306+1. Clone `react-native-reanimated`.
63076307+1. Navigate to `packages/docs-reanimated`.
63086308+1. Run `yarn && yarn start` to preview changes locally.
63096309+63106310+#### Documentation Structure
63116311+63126312+Maintain a consistent structure for clarity and ease of navigation:
63136313+63146314+1. **Introduction**: Briefly describe the feature.
63156315+1. **Reference**: Provide simple usage examples with type definitions.
63166316+1. **Arguments**: Detail accepted arguments.
63176317+1. **Returns**: Explain returned values.
63186318+1. **Example**: Include videos, GIFs, or interactive demos in both light and dark modes.
63196319+1. **Remarks**: Highlight non-obvious details like platform-specific quirks.
63206320+1. **Platform Compatibility**: Specify supported platforms.
63216321+63226322+#### Writing Style Guide
63236323+63246324+- Use active voice for clarity (e.g., "The function receives the arguments").
63256325+- Write short, clear sentences to aid comprehension.
63266326+- Organize information into lists for better readability.
63276327+- Avoid acronyms unless globally recognized (e.g., UI, API).
63286328+- Use contractions for a conversational tone.
63296329+63306330+#### Embedding Interactive Examples
63316331+63326332+Use the `InteractiveExample` component with `src` and `component` props to create engaging examples. For videos:
63336333+63346334+```typescript
63356335+import AnimatedKeyboardSrc from '!!raw-loader!@site/src/examples/AnimatedKeyboard';
63366336+63376337+<InteractiveExample
63386338+ src={AnimatedKeyboardSrc}
63396339+ component={
63406340+ <ThemedVideo
63416341+ center
63426342+ width={300}
63436343+ sources={{
63446344+ light: '/recordings/useAnimatedKeyboard_light.mov',
63456345+ dark: '/recordings/useAnimatedKeyboard_dark.mov',
63466346+ }}
63476347+ />
63486348+ }
63496349+/>;
63506350+```
63516351+63526352+For interactive components:
63536353+63546354+```typescript
63556355+import DecayTrain from '@site/src/examples/DecayTrain';
63566356+import DecayTrainSrc from '!!raw-loader!@site/src/examples/DecayTrain';
63576357+63586358+<InteractiveExample
63596359+ src={DecayTrainSrc}
63606360+ component={<DecayTrain />}
63616361+ label="Grab and drag the train"
63626362+/>;
63636363+```
63646364+63656365+### Contributing Code
63666366+63676367+Submit Pull Requests to address issues or introduce new features. Start with "good first issue" tasks if you're new to open-source contributions.
63686368+63696369+#### Working with Android
63706370+63716371+1. Install dependencies: `yarn && yarn build`.
63726372+1. Navigate to `apps/paper-example` and run `yarn start`.
63736373+1. Open the project in Android Studio at `react-native-reanimated/apps/paper-example/android`.
63746374+63756375+#### Working with iOS
63766376+63776377+1. Install dependencies: `yarn && yarn build`.
63786378+1. Run `cd apps/paper-example/ios && bundle install && bundle exec pod install`.
63796379+1. Start Metro bundler: `cd apps/paper-example && yarn start`.
63806380+1. Open the project in Xcode at `react-native-reanimated/apps/paper-example/ios/ReanimatedExample.xcworkspace`.
63816381+63826382+#### Preparing a Pull Request
63836383+63846384+When ready, open a Pull Request using the provided template:
63856385+63866386+1. **Summary**: Link relevant issues and describe your changes.
63876387+1. **Test Plan**: Provide instructions for testing, including code from `EmptyExample` if applicable.
63886388+63896389+#### Testing Changes Locally
63906390+63916391+To test changes in your project, create a patch with `git diff` or point to a specific commit in `package.json`.
63926392+63936393+Thank you for contributing! 🎉
63946394+63956395+## Debugging worklets
63966396+63976397+### Overview
63986398+63996399+This 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.
64006400+64016401+#### React Native Debugging Tools
64026402+64036403+The following tools have been evaluated for compatibility with React Native apps using the Reanimated library:
64046404+64056405+- **Chrome Debugger (React Native Debugger):** Utilizes a web worker in your browser to execute app JavaScript code, supporting all available runtimes in React Native.
64066406+64076407+- **Chrome DevTools:** Connects to a remote JavaScript runtime, allowing code execution on the device. Note: Not compatible with JSC.
64086408+64096409+- **Flipper (Hermes debugger):** Facilitates using Chrome DevTools and offers additional UI inspection tools.
64106410+64116411+- **Safari DevTools:** Available only for iOS devices running JSC, similar in functionality to Chrome DevTools by connecting to a remote runtime.
64126412+64136413+- **React Developer Tools:** A standalone app for debugging UI through an inspector, monitoring performance, and profiling the application.
64146414+64156415+#### JS Context vs. UI Context
64166416+64176417+Understanding 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.
64186418+64196419+#### Debugging Web Apps
64206420+64216421+For web applications, standard browser tools or any preferred debugging tools can be used without issues when employing Reanimated on the web.
64226422+64236423+### Compatibility Summary
64246424+64256425+|Tool|Platform|JSC|Hermes|V8|
64266426+|-|-|-|-|-|
64276427+|Chrome Debugger|Android|⚛️ ✅¹|⚛️ ✅¹|⚛️ ✅¹|
64286428+||iOS|⚛️ ✅¹|⚛️ ✅¹|N/A|
64296429+|Chrome DevTools|Android|N/A|⚛️ ✅²|⚛️|
64306430+||iOS|N/A|⚛️ ✅²|N/A|
64316431+|Flipper (Hermes debugger)|Android|N/A|⚛️ ✅²|⚛️|
64326432+||iOS|N/A|⚛️ ✅²|N/A|
64336433+|Safari DevTools|Android|N/A|N/A|N/A|
64346434+||iOS|⚛️ ✅|N/A|N/A|
64356435+|React Developer Tools|Android|⚛️|⚛️|⚛️|
64366436+||iOS|⚛️|⚛️|N/A|
64376437+64386438+¹ - Functions use web implementations, running worklets on the JS thread. Measure and Layout Animations are unavailable. ² - Experimental feature.
64396439+64406440+#### Legend
64416441+64426442+- ⚛️ ✅: Special features for React Native apps using Reanimated
64436443+- ⚛️: Standard functionality with no worklet debugging available
64446444+- N/A: Not applicable in React Native apps
64456445+64466446+**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.
64476447+64486448+### Tool-Specific Details
64496449+64506450+#### Chrome Debugger
64516451+64526452+|Platform|JSC|Hermes|V8|
64536453+|-|-|-|-|
64546454+|Android|⚛️ ✅|⚛️ ✅|⚛️ ✅|
64556455+|iOS|⚛️ ✅|⚛️ ✅|N/A|
64566456+64576457+**Summary:** Functions use web implementations, running on the JS thread. Measure and Layout Animations are unavailable.
64586458+64596459+#### Chrome DevTools
64606460+64616461+|Platform|JSC|Hermes|V8|
64626462+|-|-|-|-|
64636463+|Android|N/A|⚛️ ✅²|⚛️|
64646464+|iOS|N/A|⚛️ ✅²|N/A|
64656465+64666466+**Summary:** Both contexts can be debugged. This is an experimental feature.
64676467+64686468+#### Flipper (Hermes Debugger)
64696469+64706470+|Platform|JSC|Hermes|V8|
64716471+|-|-|-|-|
64726472+|Android|N/A|⚛️ ✅²|⚛️|
64736473+|iOS|N/A|⚛️ ✅²|N/A|
64746474+64756475+**Summary:** Both contexts can be debugged. This is an experimental feature.
64766476+64776477+#### Safari DevTools
64786478+64796479+|Platform|JSC|Hermes|V8|
64806480+|-|-|-|-|
64816481+|Android|N/A|N/A|N/A|
64826482+|iOS|⚛️ ✅|N/A|N/A|
64836483+64846484+**Summary:** Available only on iOS devices with the JSC engine. Worklet debugging is supported.
64856485+64866486+#### React Developer Tools
64876487+64886488+|Platform|JSC|Hermes|V8|
64896489+|-|-|-|-|
64906490+|Android|⚛️|⚛️|⚛️|
64916491+|iOS|⚛️|⚛️|N/A|
64926492+64936493+**Summary:** Functions as expected, with profiler and layout inspector available.
64946494+64956495+#### Additional Notes
64966496+64976497+- **Console Logs:** Always appear in the primary JS runtime.
64986498+64996499+- **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.
65006500+65016501+*Efforts are ongoing to enhance debugging experiences with Chrome DevTools and Flipper on Hermes.*
+59-41
out/llms-full-react-native.txt
···44444545With an understanding of how to navigate these guides, it's time to explore the foundation of React Native: Native Components.
46464747-## Animated Library Overview
4747+## Animated
48484949The `Animated` library is designed for creating fluid, powerful animations that are easy to build and maintain. It emphasizes declarative relationships between inputs and outputs, configurable transforms, and control over animation execution through `start`/`stop` methods.
5050···922922- `hidesWhenStopped` (iOS)
923923- `size`
924924925925-## Button Component
925925+## Button
926926927927The Button component is designed to render consistently across different platforms, offering a basic level of customization. If the default appearance does not meet your needs, consider creating a custom button using Pressable. For guidance, refer to the source code of the Button component.
928928···970970||- false|||
971971972972This table summarizes the properties available for the Button component, detailing their purpose and default values where applicable.
973973+974974+## Image
973975974976To integrate image handling capabilities in your React Native application, you can utilize the `<Image />` component along with various methods and properties provided for efficient image management. Below is an overview of how to use these features effectively:
975977···1175117711761178For events with capture equivalents, the gesture state is updated once in the capture phase and can be used in the bubble phase. Be cautious with `onStartShould*` callbacks; they only reflect updated `gestureState` for start/end events that bubble/capture to the Node. Once a node becomes the responder, every start/end event updates the `gestureState`. Note that `numberActiveTouches` may not always be accurate unless you are the responder.
1177117911781178-## Installing Dependencies
11801180+## Installing dependencies
1179118111801182To develop a React Native app, ensure you have Node, Watchman, the React Native CLI, a JDK, and Android Studio installed. While any editor can be used for development, Android Studio is necessary for setting up the Android build environment.
11811183···13241326- For integrating React Native into an existing app, refer to the Integration guide.
13251327- To learn more about React Native, explore the Introduction to React Native.
1326132813271327-## ImageBackground Component Overview
13291329+## ImageBackground
1328133013291331The `<ImageBackground>` component is designed for developers who are accustomed to using `background-image` in web development. It functions similarly to the `<Image>` component, allowing you to layer additional content on top of an image.
13301332···14191421|-|-|
14201422|number|`0`|
1421142314221422-## Modal Component
14241424+## Modal
1423142514241426The Modal component provides a straightforward method to display content above an enclosing view.
14251427···15801582|-|-|
15811583|bool|`true`|
1582158415851585+## Key Concepts
15861586+15831587To integrate React Native into an existing iOS application, follow these steps carefully. This guide assumes you have a basic understanding of both iOS development using Xcode and JavaScript/React Native.
1584158815851589#### Prerequisites
···18601864|radius|number|No|Sets the radius of the ripple effect.|
18611865|foreground|boolean|No|If true, adds the ripple effect to the view's foreground instead of the background. Useful when child views have their own backgrounds or images are displayed, preventing the ripple from being obscured.|
1862186618631863-## RefreshControl Component
18671867+## RefreshControl
1864186818651869The `RefreshControl` component is designed to be used within a ScrollView or ListView, providing pull-to-refresh functionality. When the scroll position (`scrollY`) reaches zero and the user swipes down, an `onRefresh` event is triggered.
18661870···2107211121082112> **Deprecated Notice:** The support for TV devices has been transitioned to a separate repository named "React Native for TV." For detailed guidance on projects targeting Apple TV or Android TV, please refer to the *README* file within that repository.
2109211321142114+## ScrollView
21152115+21102116The provided documentation outlines various properties and methods associated with a ScrollView component, likely from a mobile development framework such as React Native. Below is a summary of the key features:
2111211721122118#### Properties
···2214222022152221Here, `"providesModuleNodeModules"` is a list of modules added to the Haste module search path, and `"platforms"` specifies valid platform suffixes.
2216222222172217-## StatusBar Component
22232223+## StatusBar
2218222422192225The `StatusBar` component manages the app's status bar, which is typically located at the top of the screen. It displays information such as time, network status, battery level, and other status icons.
22202226···23842390|`'light-content'`|string|White texts and icons.|
23852391|`'dark-content'`|string|Dark texts and icons (requires API>=23 on Android).|
2386239223872387-## Enabling USB Debugging on Android Devices
23932393+## 1. Enable Debugging over USB
2388239423892395Most Android devices restrict app installations to those downloaded from Google Play by default. To install apps during development, enable USB Debugging on your device.
23902396···2515252125162522This guide covers enabling USB debugging, setting up an Android device for React Native development, connecting to the development server via USB or Wi-Fi, and preparing your app for production release. Follow these steps to streamline your development workflow.
2517252325182518-## Switch Component
25242524+## Switch
2519252525202526The `Switch` component renders a boolean input and functions as a controlled component. It necessitates an `onValueChange` callback to update its `value` prop, ensuring that user interactions are accurately reflected in the UI. Without updating the `value` prop, the component will persistently display the initially supplied value.
25212527···25702576- **Description**: Determines the state of the switch. If set to `true`, the switch is on; otherwise, it's off. The default value is `false`.
25712577- **Type**: `bool`
2572257825732573-## Fast Refresh in React Native
25792579+## Fast Refresh
2574258025752581Fast Refresh is a feature in React Native that provides near-instant feedback when changes are made to your React components. By default, this feature is enabled and can be toggled through the "Enable Fast Refresh" option in the React Native Dev Menu. With it activated, most edits should become visible within seconds.
25762582···2620262626212627This behavior can lead to unexpected results, such as an empty-array `useEffect` running once during Fast Refresh. Writing resilient code for occasional `useEffect` re-runs is beneficial and aligns with best practices, facilitating future dependency additions.
2622262826232623-## Metro Configuration in React Native
26292629+## Metro
2624263026252631React Native utilizes Metro to compile JavaScript code and manage assets. Below are guidelines for configuring Metro within your project.
26262632···27122718- Visit the [Metro website](https://metrobundler.dev/docs/configuration) for more information.
27132719- Watch the "Metro & React Native DevX" talk at App.js 2023 for insights into Metro's role in React Native development.
2714272027152715-## Using Libraries in React Native
27212721+## Using Libraries
2716272227172723React Native offers built-in Core Components and APIs, but you can also leverage a vast community of developers to find additional libraries that extend your app's functionality.
27182724···28202826```shell
28212827npm install @react-native-community/netinfo@^2.0.0
28222828```
28292829+28302830+## Text
2823283128242832Here's a structured overview and explanation of the `Text` component in React Native, focusing on its properties and usage:
28252833···2895290328962904The `Text` component in React Native is highly customizable, supporting various styling and accessibility options. Understanding its properties allows developers to create rich, interactive text elements tailored to specific application needs.
2897290529062906+## TextInput
29072907+28982908Here is a structured overview of the properties, methods, and known issues related to the `TextInput` component in React Native:
2899290929002910#### Properties
···2971298129722982This overview provides a comprehensive guide to using and understanding the `TextInput` component in React Native, including its properties, methods, and known issues.
2973298329742974-## TouchableHighlight Component
29842984+## TouchableHighlight
2975298529762986> For a more robust and future-proof approach to handling touch-based input, consider using the Pressable API.
29772987···30413051- **testOnly\_pressed**: Useful for snapshot tests.
30423052 - Type: bool
3043305330443044-## TouchableOpacity Component
30543054+## TouchableOpacity
3045305530463056> For a more comprehensive and future-proof approach to handling touch-based input, consider using the Pressable API.
30473057···31063116- **Platform**: Android
31073117- Description: Identifies the next focusable view when navigating up using a TV remote, as detailed in the View component documentation.
3108311831093109-## Upgrading React Native Versions
31193119+## Upgrading to new versions
3110312031113121Upgrading to newer versions of React Native provides access to additional APIs, views, developer tools, and other enhancements. Although the process requires some effort, we aim to make it as straightforward as possible.
31123122···32233233|`testID`|Used to locate this view in end-to-end tests.|string|
32243234|`touchSoundDisabled` (Android)|If set to true, prevents the system sound from playing on touch.|Boolean|
3225323532263226-## Text
32363236+## View
3227323732283238#### Accessibility Properties
32293239···3317332733183328This documentation provides comprehensive details on how to configure various aspects of a `View`, focusing on accessibility, layout, interaction, and identification.
3319332933203320-## Style in React Native
33303330+## Style
3321333133223332In React Native, styling your application is done using JavaScript. Core components accept a `style` prop, which typically mirrors CSS conventions but uses camel casing for property names (e.g., `backgroundColor` instead of `background-color`).
33233333···3379338933803390To occupy a specific portion of the screen without using the `flex` layout, you can use **percentage values** in the component's style. Like flex dimensions, percentage dimensions require that the parent has defined dimensions.
3381339133823382-## DrawerLayoutAndroid Component
33923392+## DrawerLayoutAndroid
3383339333843394The `DrawerLayoutAndroid` is a React component specifically designed for Android platforms. It encapsulates the platform's native `DrawerLayout`. This layout typically serves as a navigation drawer, which can be rendered using the `renderNavigationView` prop. The main content of your application resides within its direct children.
33853395···3516352635173527Opens the navigation drawer.
3518352835193519-## Flexbox Layout in React Native
35293529+## Layout with Flexbox
3520353035213531Flexbox provides a consistent way to design layouts across different screen sizes. In React Native, it shares similarities with CSS on the web but has specific differences such as default values for properties like `flexDirection`, `alignContent`, and `flexShrink`.
35223532···39563966- **react-native#18997**: Does not support multiline `TextInput`.
39573967- **react-native#20157**: Incompatible with a bottom tab bar.
3958396839593959-## SafeAreaView Overview
39693969+## SafeAreaView
3960397039613971The `SafeAreaView` component ensures that content is displayed within the safe area boundaries of a device. It's specifically designed for iOS devices running version 11 or later.
39623972···3974398439753985`SafeAreaView` inherits all View Props. Note that any padding specified in styles applied to a `SafeAreaView` will be ignored, as the component uses its own padding logic. This can lead to different results across platforms. For more details, refer to issue #22211.
3976398639773977-## Image Style Properties
39873987+## Image Style Props
3978398839793989### Examples
39803990···41374147|-|
41384148|color|
4139414941404140-## Shadow Properties in React Native
41504150+## Shadow Props
4141415141424152- TypeScript
41434153- JavaScript
···42154225|-|
42164226|number|
4217422742184218-## Text Style Properties
42284228+## Text Style Props
4219422942204230### Example
42214231···43894399 - `'all'`
43904400- **Default**: `none`
4391440143924392-## View Style Properties
44024402+## View Style Props
4393440343944404### Example
43954405···4685469546864696- `boxShadow`
4687469746884688-## Handling Touches in React Native
46984698+## Handling Touches
4689469946904700Users primarily interact with mobile applications through touch gestures such as tapping buttons, scrolling lists, or zooming maps. React Native offers components to manage common gestures and a comprehensive gesture responder system for advanced recognition. The `Button` component is particularly useful for basic interactions.
46914701···5229523952305240React Navigation also offers packages for different navigators, such as tabs and drawers, enabling various navigation patterns in your app. For a comprehensive introduction to React Navigation, refer to the React Navigation Getting Started Guide.
5231524152325232-## Troubleshooting Guide for React Native Setup
52425242+## Troubleshooting
5233524352345244This guide addresses common issues encountered during the setup of React Native. If you face an issue not listed here, consider searching for it on GitHub.
52355245···5673568356745684Having covered React and React Native’s Core Components, let's explore handling `<TextInput>` further.
5675568556765676-## Core Components and APIs in React Native
56865686+## Core Components and APIs
5677568756785688React Native offers a variety of built-in core components that can be utilized directly within your application. These components are accessible via the navigation sidebar or the top menu for narrower screens.
56795689···58985908export default MyScrollView;
58995909```
5900591059015901-## Using List Views in React Native
59115911+## Using List Views
5902591259035913React Native offers several components designed for presenting lists of data efficiently. The primary choices are `FlatList` and `SectionList`.
59045914···6085609560866096**Pro tip:** Configure your Web bundler to ignore `.native.js` extensions to avoid including unused code in production, reducing bundle size.
6087609760986098+## Accessibility
60996099+60886100#### Overview of Accessibility Features in React Native
6089610160906102React Native provides several accessibility features that help developers create applications usable by everyone, including people with disabilities. These features are crucial for ensuring inclusivity and compliance with accessibility standards like WCAG (Web Content Accessibility Guidelines).
···64666478- Safari Developer Tools (Direct JSC Debugging)
64676479- Remote JavaScript Debugging (Removed)
6468648064696469-## Testing Guide for Code Quality Assurance
64816481+## Testing
6470648264716483As your codebase grows, small errors can lead to significant failures. Bugs negatively impact user experience and business outcomes. To prevent fragile programming, testing is essential before releasing software.
64726484···70027014|userInterfaceStyleiOS|string|Interface style for the alert, set to `light` or `dark`, otherwise defaults to system style.|
70037015|onDismissAndroid|function|Callback fired when the alert is dismissed.|
7004701670057005-## Optimizing JavaScript Loading
70177017+## Optimizing JavaScript loading
7006701870077019Parsing and executing JavaScript code requires both memory and time. As applications grow, it becomes beneficial to delay loading code until it's needed for the first time. React Native includes standard optimizations by default, but additional techniques can further enhance app efficiency. For very large apps, advanced automatic optimizations are available, though they come with tradeoffs.
70087020···7944795679457957This structure is generated using the value `all` for `codegenConfig.type`. Use `modules` to exclude `react/renderer/components/`, and `components` to exclude other files.
7946795879477947-## Codegen CLI Overview
79597959+## The Codegen CLI
7948796079497961The **Codegen** CLI simplifies running tasks by eliminating the need to remember complex commands or manually execute scripts. It facilitates executing `@react-native/codegen` for React Native projects with ease.
79507962···8013802580148026By following these steps, you can streamline your development process and ensure that your library remains compatible with various React Native versions.
8015802780168016-## Introduction
80288028+## Native Platform
8017802980188030### Overview
80198031···80478059**Previous:** The Codegen CLI\
80488060**Next:** Android and iOS
8049806180508050-## BackHandler API Overview
80628062+## BackHandler
8051806380528064The **BackHandler** API is designed for Android devices to manage hardware button presses related to back navigation. It allows developers to register event listeners and control the application's response to these events.
80538065···81178129```typescript
81188130static exitApp();
81198131```
81328132+81338133+## Native Modules
8120813481218135To implement a cross-platform `localStorage` solution using React Native's TurboModule system, you need to set up both Android and iOS platforms. Below is a step-by-step guide based on the provided instructions:
81228136···83478361 ```
8348836283498363This setup provides a consistent `localStorage` API across both platforms using React Native's TurboModule system.
83648364+83658365+## Cross-Platform Native Modules (C++)
8350836683518367Creating a cross-platform native module using C++ is an efficient way to share platform-agnostic code between Android and iOS. This guide walks through the process of creating a pure C++ Turbo Native Module, which allows you to write your logic once and reuse it across platforms.
83528368···8671868786728688You've successfully created a C++ Turbo Native Module that works on both Android and iOS. This setup allows you to write platform-agnostic code in C++, reducing redundancy and improving maintainability across platforms.
8673868986908690+## Native Components
86918691+86748692To create a native web view component in React Native, you need to implement platform-specific code for both Android and iOS. Below is a step-by-step guide on how to achieve this:
8675869386768694#### Step 1: Set Up Your Project
···9123914191249142Congratulations! You've published your first React Native library.
9125914391269126-## ToastAndroid API in React Native
91449144+## ToastAndroid
9127914591289146The `ToastAndroid` API in React Native provides access to Android's native toast notifications. It offers methods for displaying short or long messages with optional positioning and offset adjustments.
91299147···9423944194249442If native usage is required, include the library's headers by going to your project file, selecting `Build Settings`, and searching for `Header Search Paths`. Add the path to your library. (Previously recommended using `recursive` is now discouraged due to potential build failures, especially with CocoaPods.)
9425944394269426-## Running on Simulator
94449444+## Running On Simulator
9427944594289446### Starting the Simulator
94299447···9751976997529770**Example:**
9753977197549754-## Appearance Module
97729772+## Appearance
9755977397569774The `Appearance` module provides information about the user's appearance preferences, such as their preferred color scheme (light or dark).
97579775···10643106611064410662> **Note**: Ensure any `View` intended to receive accessibility focus has `accessible={true}`.
10645106631064610646-## AppState Overview
1066410664+## AppState
10647106651064810666The `AppState` module provides information about whether an application is in the foreground or background and notifies you of any state changes. It's particularly useful for determining how to handle push notifications based on the app's current state.
1064910667···11672116901167311691A line with `hairlineWidth` might not be visible if your simulator is downscaled.
11674116921167511675-## Dimensions in React Native
1169311693+## Dimensions
11676116941167711695`useWindowDimensions` is the recommended API for React components, as it updates automatically with changes to the window's dimensions. This aligns well with the React paradigm.
1167811696···1176511783|scale|number|
1176611784|fontScale|number|
11767117851176811768-## Props in React Native
1178611786+## Props
11769117871177011788In React Native, most components are customizable through parameters known as `props`, short for properties. These allow developers to tailor component behavior and appearance.
1177111789···12010120281201112029Register the value to the profile name on the systrace timeline.
12012120301201312013-## Easing Module
1203112031+## Easing
12014120321201512033The `Easing` module provides a collection of common easing functions used to create physically believable motion in animations, particularly with `Animated.timing()`.
1201612034···12497125151249812516Indicates the width in pixels of the window or screen that your application occupies.
12499125171250012500-## Keyboard Module
1251812518+## Keyboard
12501125191250212520The `Keyboard` module provides functionality for controlling and responding to keyboard events in your application. It allows you to listen for native keyboard notifications, dismiss the keyboard, and synchronize layout animations with keyboard movements.
1250312521