# react-native-reanimated
### Create Smooth Animations with an Excellent Developer Experience
#### Why Choose Reanimated?
##### Declarative API
Reanimated offers a declarative approach to creating animations, simplifying complexity from numerous methods down to just a few. Define the desired animation outcome and let Reanimated handle the style and property animations for you.
##### High Performance
With Reanimated, define animations in plain JavaScript that run natively on the UI thread by default. This ensures smooth interactions up to 120 fps or more, delivering a native experience users expect.
##### Rich Features
Reanimated's capabilities extend beyond animating simple views or images. Integrate your animations with device sensors or keyboards, utilize Layout Animations, and effortlessly animate elements between navigation screens.
- **Learn More**: Discover the features of Reanimated 3 in our latest article.
- [See blog post](#)
##### Animation Capabilities
Animate every React Native prop on iOS, Android, and the Web up to 120 fps.
```typescript
function App() {
const width = useSharedValue(100);
const handlePress = () => {
width.value = withSpring(width.value + 50);
};
return ;
}
```
##### Gesture Integration
Experience smooth gestures through Reanimated's integration with React Native Gesture Handler.
```typescript
import { Gesture, GestureDetector } from "react-native-gesture-handler";
function App() {
const pan = Gesture.Pan();
return (
);
}
```
##### Layout Animations
Automatically animate views when they are added or removed from the view hierarchy.
```typescript
function App() {
return ;
}
```
##### Sensor-Based Animations
Easily connect your animations to a gyroscope or accelerometer with just one hook.
```typescript
const gyroscope = useAnimatedSensor(SensorType.GYROSCOPE)
useDerivedValue(() => {
const { x, y, z } = gyroscope.sensor.value
})
```
##### Keyboard-Based Animations
Create animations based on the device keyboard state and position.
```typescript
function App() {
const keyboard = useAnimatedKeyboard()
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateY: -keyboard.height.value }],
}))
//...
}
```
##### Shared Element Transitions
Seamlessly animate elements between navigation screens with a single line of code.
```typescript
function App() {
return ;
}
```
#### Sponsors
### We are Software Mansion
React Native Core Contributors and experts in addressing all types of React Native issues. Whether you need assistance with gestures, animations, or general React Native development, we're here to help.
## useAnimatedStyle
`useAnimatedStyle` is a hook that allows you to create an animated styles object, similar to `StyleSheet`, which can be dynamically updated using shared values. These styles must be applied to the `style` property of an Animated component and are automatically refreshed when associated shared values or React state change.
Unlike inline styling, `useAnimatedStyle` provides access to values stored in shared values within the defined style object. For animating properties directly on components, consider using `useAnimatedProps`.
### Reference
```typescript
import { useAnimatedStyle } from 'react-native-reanimated';
function App() {
const animatedStyles = useAnimatedStyle(() => ({
opacity: sv.value ? 1 : 0,
}));
return ;
}
```
#### Arguments
##### `updater`
A function that returns an object containing the style properties you wish to animate. Any style property available in React Native can be animated.
##### `dependencies` (Optional)
An optional array of dependencies. This is only relevant when using Reanimated without its Babel plugin on the Web.
### Returns
The hook returns an animated style object, which should be assigned to the `style` property of an Animated component you wish to animate. The `updater` callback provides a value resembling a regular style object that can incorporate shared values.
### Example
#### Remarks
- Animated styles override React Native's static styles. Values in animated styles take precedence over those from static styles.
```typescript
function App() {
const animatedStyles = useAnimatedStyle(() => ({
width: sv.value,
}));
return (
);
}
```
- The order of animated styles in a style array does not affect their application. The most recently updated animated style is applied.
- Removing an animated style from a view does not revert values set by that style. To reset these values, explicitly set them to `undefined` within the animated style.
- Modifying shared values inside the `useAnimatedStyle` callback can lead to undefined behavior and potential infinite loops.
```typescript
function App() {
const sv = useSharedValue(0)
const animatedStyles = useAnimatedStyle(() => {
sv.value = withTiming(1) // Avoid this!
return { opacity: sv.value }
})
}
```
- Animated styles should only be applied to `Animated` components. Applying them to non-animated components will cause an error.
- Define dynamic styles using `useAnimatedStyle`, while keeping static styles separate via the `StyleSheet` API or inline styles. This minimizes unnecessary style recalculations. Static and dynamic styles can be merged using array syntax:
```typescript
function App() {
const animatedStyles = useAnimatedStyle(() => ({
offset: sv.value,
}));
return ;
}
const styles = StyleSheet.create({
box: {
height: 120,
width: 120,
backgroundColor: '#b58df1',
},
});
```
- Animated styles can be shared between components to reduce code duplication.
- The callback for `useAnimatedStyle` executes on both the JavaScript and UI threads. To ensure thread-specific behavior, use the `global._WORKLET` variable:
```typescript
function App() {
const animatedStyles = useAnimatedStyle(() => {
if (global._WORKLET) {
// Code specific to the UI thread
} else {
// Fallback code for the JS thread
}
})
}
```
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Shared Element Transitions
> **Caution:**\
> Shared Element Transition is an experimental feature and not recommended for production use yet. Feedback is welcomed to enhance its implementation.
Shared Element Transition enables a smooth transformation of a component from one screen to another.
### Reference
```typescript
import Animated from 'react-native-reanimated';
const Stack = createNativeStackNavigator();
function One({ navigation }) {
return (
<>
navigation.navigate('Two')} />
>
);
}
function Two({ navigation }) {
return (
<>
navigation.navigate('One')} />
>
);
}
export default function SharedElementExample() {
return (
);
}
```
### Overview
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.
Without custom animations, properties like `width`, `height`, `originX`, `originY`, and `transformMatrix` animate by default over 500ms using `withTiming`.
### Implementation
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.
**Screen A**
```typescript
```
**Screen B**
```typescript
```
### Custom Animation
Custom animations can be created using `SharedTransition.custom` for regular animations or `SharedTransition.progressAnimation` for progress-based ones.
```typescript
import { SharedTransition } from "react-native-reanimated"
const transition = SharedTransition.custom((values) => {
"worklet"
return {
height: withSpring(values.targetHeight),
width: withSpring(values.targetWidth),
}
})
.progressAnimation((values, progress) => {
"worklet"
const getValue = (
progress: number,
target: number,
current: number
): number => {
return progress * (target - current) + current
}
return {
width: getValue(progress, values.targetWidth, values.currentWidth),
height: getValue(progress, values.targetHeight, values.currentHeight),
}
})
.defaultTransitionType(SharedTransitionType.ANIMATION)
```
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.
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.
```typescript
```
### Example
Your browser does not support the video tag.
Your browser does not support the video tag.
Expand the full code:
```typescript
goToDetails('countryside')}>
goToDetails('florence')}>
goToDetails('dawn')}>
```
### Remarks
- Only the native stack is supported.
- Animatable properties include `width`, `height`, `originX`, `originY`, and `transformMatrix`.
- Layout for shared view children isn't computed during transitions.
- Currently supports only the old React Native architecture (Paper).
- Future support for the new React Native architecture (Fabric) is planned.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|❌|
## Troubleshooting
### Initialization Issues
Reanimated consists of four core components that must align within the same minor version:
- C++
- Java
- JavaScript
- Reanimated Babel plugin.
Discrepancies in these components, especially when transpiled with different versions of the Reanimated Babel plugin, can lead to undefined behavior and errors.
#### Failed to Create a Worklet
**Problem:** This typically occurs if Reanimated is not installed correctly, such as omitting the Reanimated Babel plugin from `babel.config.js`.
**Solution:** Refer to the installation documentation at [Reanimated Getting Started](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#step-2-add-reanimateds-babel-plugin) for guidance.
#### Native Part of Reanimated Doesn't Seem to Be Initialized
**Problem:** This issue arises when the native side of Reanimated fails to initialize from JavaScript.
**Solution:**
1. Ensure your app is rebuilt after installing or upgrading Reanimated.
1. Verify that your platform is supported by Reanimated, including:
- Android
- iOS
- macOS
- tvOS
- visionOS
- Web
1. For brownfield apps, manually initialize the native library.
#### Unknown Version of Reanimated Babel Plugin
**Problem:** This occurs when the JavaScript side cannot retrieve the version of the Reanimated Babel plugin.
**Solution:**
1. Check if any part of your code is transpiled with an outdated version of the Reanimated Babel plugin.
1. Ensure you are not using a release bundle with a debug build, as this is unsupported.
#### Mismatch Between JavaScript Code Version and Reanimated Babel Plugin Version
**Problem:** This can happen when code is transpiled with an outdated version of the Reanimated Babel plugin.
**Solution:** Reset your Metro bundler cache using `yarn start --reset-cache`, `npm start -- --reset-cache`, or `expo start -c` and rerun the app. If issues persist, identify dependencies that may contain outdated worklets by examining error messages.
#### Using Dev Bundle in a Release App Build is Not Supported
**Problem:** This occurs when a release build uses a development JavaScript bundle.
**Solution:** Refer to relevant documentation for more information.
#### Couldn't Determine the Version of the Native Part of Reanimated
**Problem:** This happens when Reanimated cannot determine its native part's version.
**Solution:** Ensure your app is rebuilt after upgrading `react-native-reanimated`. For Expo Go users, use the exact version bundled with the Expo SDK.
#### Mismatch Between JavaScript and Native Parts of Reanimated
**Problem:** This occurs when different versions of the JavaScript and native parts are used.
**Solution:** Confirm that your app is rebuilt post-upgrade. For Expo Go, ensure compatibility with the bundled version in the Expo SDK.
#### C++ Side Failed to Resolve JavaScript Code Version
See "Couldn't Determine the Version of the Native Part of Reanimated" and "Unknown Version of Reanimated Babel Plugin."
#### Mismatch Between C++ Code Version and JavaScript Code Version
Refer to issues regarding mismatches between JavaScript parts, native parts, and the Reanimated Babel plugin.
#### C++ Side Failed to Resolve Java Code Version
**Problem:** This occurs when the version of the Java part cannot be determined, likely due to a missed rebuild after an upgrade.
**Solution:** Rebuild your app and check if the issue persists. If it does, consider reporting it on GitHub.
#### Mismatch Between C++ Code Version and Java Code Version
Refer to "Native Side Failed to Resolve Java Code Version."
#### Java Side Failed to Resolve C++ Code Version
**Problem:** This happens when the version of the C++ part cannot be determined, likely due to a missed rebuild after an upgrade.
**Solution:** Refer to "Native Side Failed to Resolve Java Code Version."
#### Mismatch Between Java Code Version and C++ Code Version
Refer to "Native Side Failed to Resolve Java Code Version."
#### Multiple Versions of Reanimated Were Detected
**Problem:** This error occurs when more than one instance of Reanimated exists in your project, often due to dependencies installing it within their own `node_modules`.
**Solution:**
- For Yarn users, add a `resolutions` property in `package.json`:
```json
"resolutions": {
"react-native-reanimated": ""
}
```
- For npm users, use the `overrides` property:
```json
"overrides": {
"react-native-reanimated": ""
}
```
Afterward, run your package manager again (`yarn` or `npm install`).
#### Another Instance of Reanimated Was Detected
Refer to "Multiple Versions of Reanimated Were Detected."
#### Outdated Version of React Native for New Architecture
**Problem:** Reanimated supports the New Architecture (Fabric) only on the latest minor release of React Native.
**Solution:** Upgrade to a newer version of React Native or downgrade Reanimated. Consult the compatibility table for supported versions.
### Warnings
#### Reduced Motion Setting is Enabled on This Device
**Problem:** This warning helps avoid confusion when reduced motion is enabled.
**Solution:** Ignore this warning in development mode as it's safe. To disable, add:
```javascript
LogBox.ignoreLogs([
"[Reanimated] Reduced motion setting is enabled on this device.",
])
```
#### Tried to Modify Key of an Object Which Has Been Converted to a Shareable
**Problem:** This warning indicates that a shared value should be used or objects in worklets accessed more granularly.
##### 1. Not Using Shared Values
Example:
```javascript
const obj = { prop: 1 }
function worklet() {
"worklet"
console.log(obj.prop)
}
runOnUI(worklet)()
obj.prop = 2 // Warning occurs here.
runOnUI(worklet)()
```
**Solution:** Use a shared value instead:
```typescript
const sv = useSharedValue({ prop: 1 })
function worklet() {
"worklet"
console.log(sv.value.prop)
}
runOnUI(worklet)()
sv.value = { prop: 2 } // Correct usage.
```
##### 2. Not Accessing Object Properties Granularly
Example:
```javascript
const obj = { propAccessedInWorklet: 1, propNotAccessedInWorklet: 2 }
function worklet() {
"worklet"
console.log(obj.propAccessedInWorklet)
}
runOnUI(worklet)()
obj.propNotAccessedInWorklet = 3 // Warning occurs here.
```
**Solution:** Assign accessed properties to variables beforehand:
```typescript
const obj = { propAccessedInWorklet: 1, propNotAccessedInWorklet: 2 }
const propAccessedInWorklet = obj.propAccessedInWorklet
function worklet() {
"worklet"
console.log(propAccessedInWorklet)
}
runOnUI(worklet)()
obj.propNotAccessedInWorklet = 3 // Correct usage.
```
### Threading Issues
#### Tried to Synchronously Call a Non-Worklet Function on the UI Thread
**Problem:** This occurs when calling a non-worklet function from within a worklet.
Example:
```javascript
function callee() {
console.log("hello")
}
function caller() {
"worklet"
callee() // Error here.
}
runOnUI(caller)()
```
**Solution:**
1. Mark the function as a worklet using `worklet` directive:
```typescript
function callee() {
"worklet"
console.log("hello")
}
```
1. Execute the function on the JS thread with `runOnJS`:
```typescript
function caller() {
"worklet"
runOnJS(callee)()
}
```
For more information, refer to Reanimated's documentation on worklets.
## useAnimatedScrollHandler
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.
### Reference
```typescript
import { useAnimatedScrollHandler } from 'react-native-reanimated';
function App() {
const offsetY = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler((event) => {
offsetY.value = event.contentOffset.y;
});
// ...
return ;
}
```
#### Arguments
##### `handlers`
An object containing custom keys that correspond to native event names. Available keys include:
- `onScroll`
- `onBeginDrag`
- `onEndDrag`
- `onMomentumBegin`
- `onMomentumEnd`
Each key should map to an individual worklet function. These functions are triggered when the associated events occur on a connected Scrollable component.
The event worklets receive two parameters:
- `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.
- `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.
##### `dependencies` (Optional)
An optional array of dependencies, relevant only when using Reanimated without the Babel plugin on the Web.
#### Returns
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`.
### Example
### Remarks
- The returned handler can be passed to multiple components. It will invoke for the specified events whenever any component dispatches them.
- 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.
- Only the `onScroll` event is supported on Web.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useAnimatedScrollHandler
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.
### Reference
```typescript
import { useAnimatedScrollHandler } from 'react-native-reanimated';
function App() {
const offsetY = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler((event) => {
offsetY.value = event.contentOffset.y;
});
// ...
return ;
}
```
#### Arguments
##### `handlers`
An object containing custom keys that correspond to native event names. Available keys include:
- `onScroll`
- `onBeginDrag`
- `onEndDrag`
- `onMomentumBegin`
- `onMomentumEnd`
Each key should map to an individual worklet function. These functions are triggered when the associated events occur on a connected Scrollable component.
The event worklets receive two parameters:
- `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.
- `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.
##### `dependencies` (Optional)
An optional array of dependencies, relevant only when using Reanimated without the Babel plugin on the Web.
#### Returns
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`.
### Example
### Remarks
- The returned handler can be passed to multiple components. It will invoke for the specified events whenever any component dispatches them.
- 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.
- Only the `onScroll` event is supported on Web.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useEvent
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`.
### Reference Usage
```typescript
import { useEvent } from 'react-native-reanimated';
function useAnimatedPagerScrollHandler(handlers, dependencies) {
const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
return useEvent(
(event) => {
'worklet';
const { onPageScroll } = handlers;
if (onPageScroll && event.eventName.endsWith('onPageScroll')) {
onPageScroll(event, context);
}
},
['onPageScroll'],
doDependenciesDiffer
);
}
return ;
```
#### Arguments
- **`handler`**: A function that receives an event object containing the native payload. This can be utilized within custom handler hooks' worklets.
- `event`: The event object, whose payload varies based on the event type.
- **`eventNames` (Optional)**: An array specifying which event names should trigger the handler.
- **`rebuild` (Optional)**: A boolean indicating if the handler needs to be rebuilt.
#### Returns
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.
### Example
For simpler implementations, consider using `useScrollViewOffset`.
### Remarks
- Note that not all scroll events are supported on the web; only `onScroll` is consistently available across browsers.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This overview provides a concise guide to using the `useEvent` hook effectively within React Native Reanimated projects.
## useHandler
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`.
### Reference
```typescript
import { useEvent, useHandler } from "react-native-reanimated"
function useAnimatedPagerScrollHandler(
handlers: Record void>,
dependencies?: any[]
) {
const { context, doDependenciesDiffer, useWeb } = useHandler(
handlers,
dependencies
)
return useEvent(
(event: any) => {
"worklet"
const { onPageScroll } = handlers
if (onPageScroll && event.eventName.endsWith("onPageScroll")) {
onPageScroll(event, context)
}
},
["onPageScroll"],
doDependenciesDiffer
)
}
```
#### Arguments
##### `handlers`
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.
Each event worklet receives:
- `event`: An event object whose payload varies based on the event type.
- `context`: A plain JavaScript object for storing state, persisting between events. This allows communication among multiple event handlers provided as an object of worklets.
##### `dependencies` (Optional)
An optional array of dependencies. This is relevant when using Reanimated without its Babel plugin in a web environment.
#### Returns
The hook returns:
- A context reused by event handlers.
- An indicator to determine if worklets should be rebuilt.
- A boolean, `useWeb`, to check for the web environment if different implementations are needed.
### Example
For simpler implementations, consider using `useScrollViewOffset`.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This documentation provides a comprehensive overview of how to utilize the `useHandler` hook within React Native Reanimated for creating custom event handlers.
## Keyframe animations
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.
### Reference
```typescript
import { Keyframe } from 'react-native-reanimated';
const keyframe = new Keyframe({
0: {
transform: [{ rotate: '0deg' }],
},
45: {
transform: [{ rotate: '100deg' }],
easing: Easing.exp,
},
100: {
transform: [{ rotate: '45deg' }],
},
});
function App() {
return ;
}
```
#### Arguments
##### `definitions`
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.
Key values include:
- `0` or `from`: Represents the initial state.
- Intermediate points (e.g., `45`): Represent intermediate states.
- `100` or `to`: Represents the final state.
The key `0` (or `from`) should define the style at the start of the animation, while `100` (or `to`) defines it at the end.
### Modifiers
```typescript
keyframe
.duration(1000)
.delay(500)
.reduceMotion(ReduceMotion.Never)
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(durationMs: number)` sets the animation length in milliseconds, defaulting to `500`.
- `.delay(durationMs: number)` specifies a delay before starting the animation, defaulting to `0`.
- `.reduceMotion(reduceMotion: ReduceMotion)` adjusts the animation based on the device's reduced motion setting.
- `.withCallback(callback: (finished: boolean) => void)` triggers after the animation ends, indicating if it finished without interruptions.
### Remarks
- Providing keyframe `0` or `from` is mandatory as it defines the initial state of the object to be animated.
- Ensure all style properties intended for animation have an initial value in other keyframes.
- Easing should only be applied to subsequent keyframes, not to keyframe `0`.
- Avoid using both `0` and `from`, or `100` and `to`, as it causes parsing conflicts.
- When animating transform styles, maintain the order of properties consistently across all keyframes.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Your First Animation
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.
### Using an Animated Component
To start animating components in React Native using Reanimated, import the `Animated` object:
```typescript
import Animated from "react-native-reanimated"
```
The `Animated` object wraps native components like `View`, `ScrollView`, or `FlatList`. Use these components as you would any other JSX component:
```typescript
import Animated from 'react-native-reanimated';
export default function App() {
return (
);
}
```
### Defining a Shared Value
Shared values are essential for animations, acting like React state synchronized between JavaScript and the native side. Create shared values using `useSharedValue`:
```typescript
import { useSharedValue } from "react-native-reanimated"
```
Define shared values within your component's body to store any JS value or data structure.
For example, set a default value of `100` for width in an `Animated.View`:
```typescript
import Animated, { useSharedValue } from 'react-native-reanimated';
export default function App() {
const width = useSharedValue(100);
return (
);
}
```
### Using a Shared Value
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.
Access and modify values stored in shared values using their `.value` property:
```typescript
import { Button, View } from 'react-native';
import Animated, { useSharedValue } from 'react-native-reanimated';
export default function App() {
const width = useSharedValue(100);
const handlePress = () => {
width.value = width.value + 50;
};
return (
);
}
```
Avoid directly modifying shared values without using the `.value` property, as in `sv.value = sv.value + 100`.
### Using an Animation Function
To animate smoothly, import and use the `withSpring` function. Wrap it around the new width value to create a spring animation:
```typescript
import { Button, View } from 'react-native';
import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
export default function App() {
const width = useSharedValue(100);
const handlePress = () => {
width.value = withSpring(width.value + 50);
};
return (
);
}
```
This creates a bouncy spring animation for the element's width.
### Summary
In this section, you learned about:
- `Animated` components to define animatable elements.
- Shared values as the driving factor of animations using `useSharedValue`.
- Accessing and modifying shared values via their `.value` property (e.g., `sv.value = 100;`).
- Creating smooth animations by modifying shared values with functions like `withSpring`.
### What's Next?
In the next section, you'll explore animating styles and props using `useAnimatedStyle` and `useAnimatedProps` hooks.
## Layout transitions
Layout transitions enable smooth animations during layout changes, which may involve alterations in size and position. Both aspects can be animated for a seamless experience.
### Predefined Transitions
This section outlines the available predefined layout transitions along with their animation modifiers.
#### Linear Transition
The linear transition animates both position and dimension uniformly.
##### Reference
```typescript
import { LinearTransition } from 'react-native-reanimated';
function App() {
return ;
}
```
##### Modifiers
###### Easing (Optional)
Easing modifiers utilize the `withTiming` function to adjust animation curves over time.
```typescript
LinearTransition.easing(Easing.ease)
```
- `.easing(easingFunction: EasingFunction)`: Defines the animation curve. Defaults to `Easing.inOut(Easing.quad)`.
> Note: The `.easing(...)` modifiers are ineffective when `.springify()` is used.
###### Spring-based (Optional)
Spring-based modifiers use the `withSpring` function, allowing for physics-based (`mass`, `damping`) or duration-based (`duration`, `dampingRatio`) configurations. These properties cannot be mixed; if both sets are provided, `duration` and `dampingRatio` take precedence.
```typescript
LinearTransition.springify()
.damping(30)
.mass(5)
.rotate(20)
.stiffness(10)
.overshootClamping(false)
.restDisplacementThreshold(0.1)
.restSpeedThreshold(5)
```
- `.springify()`: Enables spring-based animation configuration.
- `.damping(value: number)`: Controls how quickly the spring stops moving. Defaults to `10`.
- `.dampingRatio(value: number)`: Determines the damping level of the spring. A value of `1` is critically damped, and values greater than `1` are overdamped. Defaults to `0.5`.
- `.mass(value: number)`: Represents the weight of the spring. Lower values result in faster animations. Defaults to `1`.
- `.rotate(degree: string)`: Allows rotation of the element.
- `.stiffness(value: number)`: Defines how bouncy the spring is; higher values mean less bounce. Defaults to `100`.
- `.overshootClamping(value: boolean)`: Determines if a spring can overshoot its target position. Defaults to `false`.
- `.restDisplacementThreshold(value: number)`: Sets the displacement below which the spring will settle without oscillations. Defaults to `0.001`.
- `.restSpeedThreshold(value: number)`: Sets the speed threshold for settling without further movement. Defaults to `2`.
###### Common (Optional)
```typescript
LinearTransition.delay(500)
.reduceMotion(ReduceMotion.Never)
.withInitialValues({ transform: [{ translateY: 420 }] })
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `300`.
- `.delay(duration: number)`: Specifies a delay before starting the animation (in milliseconds). Defaults to `0`.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts animation based on reduced motion settings.
- `.withInitialValues(values: StyleProps)`: Overrides initial animation configuration.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
##### Remarks
The animation concludes when both the speed is below `restSpeedThreshold` and the distance to its end is less than `restDisplacementThreshold`. If thresholds are not set, defaults apply.
#### Sequenced Transition
This transition animates x-position and width first, followed by y-position and height.
##### Reference
```typescript
import { SequencedTransition } from 'react-native-reanimated';
function App() {
return ;
}
```
##### Modifiers
```typescript
SequencedTransition.duration(1000)
.delay(500)
.reverse()
.reduceMotion(ReduceMotion.Never)
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `500`.
- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
- `.reverse()`: Determines if the animation should run backward. Defaults to `false`.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
#### Fading Transition
The fading transition animates opacity changes while maintaining previous position and dimensions during disappearance and appearance with new ones.
##### Reference
```typescript
import { FadingTransition } from 'react-native-reanimated';
function App() {
return ;
}
```
##### Modifiers
```typescript
FadingTransition.duration(1000)
.delay(500)
.reduceMotion(ReduceMotion.Never)
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `500`.
- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
#### Jumping Transition
The jumping transition makes components "jump" to their new positions.
##### Reference
```typescript
import { JumpingTransition } from 'react-native-reanimated';
function App() {
return ;
}
```
##### Modifiers
```typescript
JumpingTransition.duration(1000)
.delay(500)
.reduceMotion(ReduceMotion.Never)
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `300`.
- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
#### Curved Transition
The curved transition animates all parameters (`X`, `Y`, `width`, `height`) with distinct easing functions, creating a non-linear path.
##### Reference
```typescript
import { CurvedTransition } from 'react-native-reanimated';
function App() {
return ;
}
```
##### Modifiers
```typescript
CurvedTransition.duration(1000)
.delay(500)
.easingX(Easing.inOut(Easing.ease))
.easingY(Easing.inOut(Easing.ease))
.easingWidth(Easing.inOut(Easing.ease))
.easingHeight(Easing.inOut(Easing.ease))
.reduceMotion(ReduceMotion.Never)
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(duration: number)`: Sets the animation length in milliseconds. Defaults to `300`.
- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
- `.easingX(easing: EasingFunction)`: Defines easing for x-position.
- `.easingY(easing: EasingFunction)`: Defines easing for y-position.
- `.easingWidth(easing: EasingFunction)`: Defines easing for width.
- \`.easingHeight(easing: EasingFunction)): Defines easing for height.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
##### Remarks
The duration is shared across all easings.
#### Entry/Exit Transition
This transition allows for custom animations during entry and exit by combining both into one layout. Users can define their own animations instead of using predefined ones.
##### Reference
```typescript
import { EntryExitTransition } from 'react-native-reanimated';
function App() {
return ;
}
```
##### Modifiers
```typescript
EntryExitTransition.duration(1000)
.delay(500)
.entering(CustomEnterAnimation)
.exiting(CustomExitAnimation)
.reduceMotion(ReduceMotion.Never)
.withCallback((finished) => {
console.log(`finished without interruptions: ${finished}`)
})
```
- `.duration(duration: number)`: Sets the animation length in milliseconds. Default depends on entry/exit animations.
- `.delay(duration: number)`: Specifies a delay before starting (in milliseconds). Defaults to `0`.
- `.exiting(animation)`: Defines the exit animation. Defaults to `FadeOut`.
- `.entering(animation)`: Defines the entry animation. Defaults to `FadeIn`.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts based on reduced motion settings.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
##### Remarks
The duration is the sum of entering and exiting durations.
#### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This table indicates that all predefined transitions are compatible across Android, iOS, and web platforms.
## Incremental Migration from Reanimated 1 to Reanimated 2
The 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.
### Renamed Methods
#### 1. `interpolate` to `interpolateNode`
- **Reanimated 1**: Use `interpolate` imported directly from `react-native-reanimated`.
- **Reanimated 2**: Replace with `interpolateNode`. If using the class member method `AnimatedValue.interpolate`, no changes are needed.
#### 2. `Easing` to `EasingNode`
- **Reanimated 1**: Use `Easing` imported from `react-native-reanimated`.
- **Reanimated 2**: Replace with `EasingNode`.
## Reanimated 3.x Overview
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.
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."
## Customizing animations
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!
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.
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.
### Configuring `withTiming`
The `config` parameter for `withTiming` includes two properties: `duration` and `easing`.
```typescript
import { withTiming, Easing } from "react-native-reanimated"
withTiming(sv.value, {
duration: 300,
easing: Easing.inOut(Easing.quad),
})
```
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.
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)`.
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.
### Configuring `withSpring`
Unlike `withTiming`, `withSpring` is physics-based and simulates real-world spring dynamics, making animations appear more realistic.
When adjusting springs, focus on these three properties: `mass`, `stiffness` (also known as *tension*), and `damping` (also known as *friction*).
```typescript
import { withSpring } from "react-native-reanimated"
withSpring(sv.value, {
mass: 1,
stiffness: 100,
damping: 10,
})
```
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.
`Stiffness` determines the bounciness of the spring, akin to comparing a steel spring (high stiffness) with one made from soft plastic (low stiffness).
`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.
Reanimated includes additional properties for customizing spring animations, which you can explore in an interactive playground or through the full `withSpring` API documentation.
### Summary
This section covered how to customize `withTiming` and `withSpring` animation functions:
- Both functions accept a `config` object as their second parameter.
- You can modify `withTiming` using `duration` and `easing`. Reanimated provides an `Easing` module for convenience.
- Key properties for adjusting `withSpring` include `mass`, `stiffness`, and `damping`.
### What's Next?
In the next section, you'll learn about animation modifiers like `withSequence` and `withRepeat`, enabling more complex and engaging animations.
## Custom animations
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.
### Reference
```typescript
function CustomAnimation(values: any) {
"worklet"
const animations = {
// Define your animations here
}
const initialValues = {
// Set initial values for animations
}
const callback = (finished: boolean) => {
// Optional callback when the layout animation ends
}
return {
initialValues,
animations,
callback,
}
}
```
### Custom Exiting Animation
#### Arguments
- `values`: Contains information about where the view was displayed and its dimensions.
- `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
- `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
- `currentWidth`: View's width.
- `currentHeight`: View's height.
- `currentBorderRadius`: View's border radius.
- `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
- `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
#### Example
```typescript
const customExiting = (values: any) => {
"worklet"
const animations = {
originX: withTiming(2 * WIDTH, { duration: 3000 }),
opacity: withTiming(0, { duration: 2000 }),
transform: [{ scale: withTiming(0.2, { duration: 3500 }) }],
}
const initialValues = {
originX: values.currentOriginX,
opacity: 1,
transform: [{ scale: 1 }],
}
return {
initialValues,
animations,
}
}
```
### Custom Entering Animation
#### Arguments
- `values`: Contains information about where the view wants to be displayed and its dimensions.
- `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
- `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
- `targetWidth`: View's width.
- `targetHeight`: View's height.
- `targetBorderRadius`: View's border radius.
- `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
- `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
#### Example
```typescript
const customEntering = (targetValues: any) => {
"worklet"
const animations = {
originX: withTiming(targetValues.targetOriginX, { duration: 3000 }),
opacity: withTiming(1, { duration: 2000 }),
borderRadius: withDelay(1500, withTiming(40, { duration: 3000 })),
transform: [
{ rotate: withTiming("0deg", { duration: 4000 }) },
{ scale: withTiming(1, { duration: 3500 }) },
],
}
const initialValues = {
originX: -WIDTH,
opacity: 0,
borderRadius: 10,
transform: [{ rotate: "90deg" }, { scale: 0.2 }],
}
return {
initialValues,
animations,
}
}
```
### Custom Layout Transition
#### Arguments
- `values`: Contains before and after information about the view's origin and dimensions.
- `targetOriginX`: X coordinate of the top-left corner in the parent's coordinate system.
- `targetOriginY`: Y coordinate of the top-left corner in the parent's coordinate system.
- `targetWidth`: View's width.
- `targetHeight`: View's height.
- `targetBorderRadius`: View's border radius.
- `targetGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system.
- `targetGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system.
- `currentOriginX`: X coordinate of the top-left corner in the parent's coordinate system (before).
- `currentOriginY`: Y coordinate of the top-left corner in the parent's coordinate system (before).
- `currentWidth`: View's width (before).
- `currentHeight`: View's height (before).
- `currentBorderRadius`: View's border radius (before).
- `currentGlobalOriginX`: X coordinate of the top-left corner in the global coordinate system (before).
- `currentGlobalOriginY`: Y coordinate of the top-left corner in the global coordinate system (before).
#### Example
```typescript
const customLayoutTransition = (values: any) => {
"worklet"
return {
animations: {
originX: withTiming(values.targetOriginX, { duration: 1000 }),
originY: withDelay(
1000,
withTiming(values.targetOriginY, { duration: 1000 })
),
width: withSpring(values.targetWidth),
height: withSpring(values.targetHeight),
},
initialValues: {
originX: values.currentOriginX,
originY: values.currentOriginY,
width: values.currentWidth,
height: values.currentHeight,
},
}
}
```
### Remarks
- 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.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|❌|
## Testing with Jest
Reanimated 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.
### Reference Example
```typescript
test('reference', () => {
// Define some styles here
const { getByTestId } = render( );
const view = getByTestId('view');
const button = getByTestId('button');
expect(view).toHaveAnimatedStyle(style);
fireEvent.press(button);
jest.advanceTimersByTime(250); // Advance time by half the animation duration (500ms)
style.width = 50; // Update width to reflect state after 250ms
expect(view).toHaveAnimatedStyle(style);
});
```
### Setup Instructions
To set up Jest for testing with Reanimated, add the following line to your `jest-setup.js` file:
```typescript
require("react-native-reanimated").setUpTests()
```
- The `setUpTests()` function can accept an optional configuration object. By default, it uses `{ fps: 60 }`.
Ensure that your `jest.config.js` includes:
```typescript
preset: 'react-native',
setupFilesAfterEnv: ['./jest-setup.js'],
```
**Caution:** For Jest versions older than 28, use the `setupFiles` property instead of `setupFilesAfterEnv`.
### API Overview
#### Style Checker
- **`expect(component).toHaveAnimatedStyle(expectedStyle)`**: Verifies that selected styles match the current component styles.
- `component`: The component being tested.
- `expectedStyle`: Expected styles, e.g., `{ width: 100 }`.
- **`expect(component).toHaveAnimatedStyle(expectedStyle, {exact: true})`**: Ensures all current component styles match expected styles.
- **`expect(component).toHaveAnimatedProps(expectedProps)`** (Available from version 3.17.2): Verifies that selected props match the current component props.
- `component`: The component being tested.
- `expectedProps`: Expected props, e.g., `{ text: 'name' }`.
- **`getDefaultStyle(component)`**: Retrieves all styles of the tested component.
#### Timers
Use Jest's fake timers to control animation progress. Refer to the Jest documentation for a comprehensive guide on mocking timers.
```typescript
jest.useFakeTimers()
// Trigger animation
jest.runAllTimers()
// For more precise control:
jest.advanceTimersByTime(250)
```
### Example Test Case
Here is an example demonstrating how to test animations:
```typescript
test('withTiming animation', () => {
const style = getDefaultStyle();
const { getByTestId } = render( );
const view = getByTestId('view');
const button = getByTestId('button');
expect(view.props.style.width).toBe(0);
expect(view).toHaveAnimatedStyle(style);
fireEvent.press(button);
jest.advanceTimersByTime(600); // Advance time by the full animation duration
style.width = 100;
expect(view).toHaveAnimatedStyle(style);
});
```
Additional examples can be found in the `react-native-reanimated` repository, such as `SharedValue.test.tsx` and `Animation.test.tsx`.
### Remarks
- Ensure tests run with Node 16 or newer.
- Testing `react-native-svg` props is not supported.
- If using a custom Babel configuration for testing, ensure Reanimated's Babel plugin is enabled.
### Recommended Testing Libraries
- [@testing-library/react-native](https://testing-library.com/docs/native-testing-library/intro)
- [@testing-library/react-hooks](https://testing-library.com/docs/react-hooks-testing-library/intro) - Useful for dealing with hooks.
## withTiming
`withTiming` enables you to create animations based on duration and easing functions.
### Reference
```typescript
import { withTiming } from "react-native-reanimated"
function App() {
sv.value = withTiming(0)
// ...
}
```
#### Arguments
##### `toValue`
The target value for the animation. Supported categories include:
- **Numbers**: Can be a number or a string representation of a number.
- **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.
- **Colors**:
- Hexadecimal integer: e.g., `0xff1234`
- RGB: e.g., `"rgb(100, 50, 0)"`
- RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
- RGB Hexadecimal: e.g., `"#53575E"`
- HSL: e.g., `"hsl(0, 50%, 50%)"`
- Named colors: e.g., `"dodgerblue"`
- **Objects**: Objects with properties that will be animated individually.
- **Arrays**: Arrays of numbers where each value is animated separately.
- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
##### `config` (Optional)
The configuration for timing animations. Available properties:
|Name|Type|Default|Description|
|-|-|-|-|
|duration|`number`|300|Length of the animation in milliseconds.|
|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
###### `Easing`
The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
Use built-in easings by passing them to the `withTiming` config:
```typescript
import { Easing } from "react-native-reanimated"
withTiming(sv.value, {
easing: Easing.bounce,
})
```
Available functions include:
- `back`: Animation where the object slightly moves back before moving forward.
- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
- `bounce`: Bouncing animation.
- `circle`: Circular function.
- `cubic`: Cubic function.
- `ease`: Simple inertial animation.
- `elastic(bounciness?: number)`: Spring interaction.
- `exp`: Exponential function.
- `linear`: Linear function.
- `poly(n: number)`: Higher power functions like quartic, quintic.
- `quad`: Quadratic function.
- `sin`: Sinusoidal function.
Helpers to modify easing functions:
- `in(easing: EasingFunction)`: Runs an easing function forwards.
- `inOut(easing: EasingFunction)`: Symmetrical easing function.
- `out(easing: EasingFunction)`: Runs an easing function backwards.
##### `callback` (Optional)
A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
#### Returns
`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`.
### Example
### Remarks
- The callback passed as the third argument is automatically workletized and executed on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useAnimatedProps
`useAnimatedProps` is a function that allows you to create an animated properties object, which can be animated using shared values. This object is particularly useful for animating properties of third-party components.
For style animations, consider using `useAnimatedStyle`.
### Reference
```typescript
import { useAnimatedProps } from 'react-native-reanimated';
function App() {
const animatedProps = useAnimatedProps(() => ({
opacity: sv.value ? 1 : 0,
}));
return ;
}
```
#### Arguments
##### `updater`
A function that returns an object containing the properties you wish to animate.
##### `dependencies` (Optional)
An optional array of dependencies. This is only relevant when using Reanimated without the Babel plugin on the Web.
##### `adapters` (Optional)
An optional function or an array of functions. Adapters are useful for handling cases where property names differ between the API surface and their native representation.
Reanimated includes two built-in adapters:
- `SVGAdapter` for managing the `transform` property in `react-native-svg`.
- `TextInputAdapter`.
You can create custom adapters using the `createAnimatedPropAdapter` function.
Example of adapting `fill` and `stroke` properties from `react-native-svg` to animate them with Reanimated:
```typescript
const adapter = createAnimatedPropAdapter(
(props) => {
if ("fill" in props) {
props.fill = { type: 0, payload: processColor(props.fill) }
}
if ("stroke" in props) {
props.stroke = { type: 0, payload: processColor(props.stroke) }
}
},
["fill", "stroke"]
)
```
#### Color-related Properties
Color properties from custom components often require special handling as they may not be directly interpretable by the native side. Reanimated includes built-in color processing for commonly used color properties, managed in a predefined list within `Colors.ts`.
For color properties not included in this list, manual processing is necessary using the `processColor` function to ensure correct interpretation on the native side.
Example of manually processing custom color properties:
```typescript
import { processColor } from "react-native-reanimated"
function App() {
const animatedProps = useAnimatedProps(() => {
const mainColor = interpolateColor(
colorProgress.value,
[0, 1],
["red", "blue"]
)
const bgColor = interpolateColor(
colorProgress.value,
[0, 1],
["green", "yellow"]
)
return {
// `colors` prop is not on our list - we need to process it manually
colors: processColor([mainColor, bgColor]),
}
})
}
```
### Returns
`useAnimatedProps` returns an animated properties object that should be assigned to the `animatedProps` property of an Animated component you wish to animate.
### Example
- You can share animated props between components to avoid code duplication.
- It is recommended to create adapters outside of a component's body to prevent unnecessary recalculations.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## React Native Reanimated: LayoutAnimationConfig (Version 3.x)
### Overview
`LayoutAnimationConfig` is a component designed to control the entering and exiting animations of its child components.
#### Reference Code
```typescript
import { LayoutAnimationConfig } from 'react-native-reanimated';
import * as React from 'react';
function App() {
const [show, setShow] = React.useState(true);
return (
{show && }
);
}
```
#### Arguments
- **`skipEntering` (Optional)**: A boolean that determines if the entering animations of child components should be skipped when `LayoutAnimationConfig` is mounted.
- **`skipExiting` (Optional)**: A boolean that determines if the exiting animations of child components should be skipped when `LayoutAnimationConfig` is unmounted.
### Example Usage
```typescript
{outer && (
{inner && (
)}
)}
```
### Remarks
- **Nesting**: The `LayoutAnimationConfig` component can be nested to disable animations for a specific subset of components.
- **FlatList Compatibility**: For `FlatList`, use the `skipEnteringExitingAnimations` prop. This automatically wraps your `FlatList` with `` to manage animations when the list is mounted or unmounted.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|❌|
- **Reference**
- Arguments
- **Example**
- **Remarks**
- **Platform Compatibility**
## Web Support
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.
### Step 1: Install the Package
Install `@babel/plugin-proposal-export-namespace-from` using one of the following package managers:
- **EXPO**
```bash
npx expo install @babel/plugin-proposal-export-namespace-from
```
- **NPM**
```bash
npm install @babel/plugin-proposal-export-namespace-from
```
- **YARN**
```bash
yarn add @babel/plugin-proposal-export-namespace-from
```
### Step 2: Add Plugins to Config File
Update your `babel.config.js` by adding the following plugins:
```javascript
module.exports = {
presets: [
// Existing presets...
],
plugins: [
...,
'@babel/plugin-proposal-export-namespace-from',
'react-native-reanimated/plugin', // Ensure this is listed last
],
};
```
**Caution:** Make sure `react-native-reanimated/plugin` is the last plugin in the list.
### Step 3: Launch Your App
To start a playground app in the browser, use:
```bash
yarn web
```
For example applications from the Reanimated repository, execute these commands at the root of the repository:
```bash
yarn && yarn build
```
Then navigate to `apps/web-example` and run:
```bash
yarn start
```
### Webpack Support
To use Reanimated in a Webpack app, adjust your configuration as follows:
Example Webpack config with Reanimated support:
```javascript
const HtmlWebpackPlugin = require("html-webpack-plugin")
const webpack = require("webpack")
module.exports = {
entry: ["babel-polyfill", "./index.js"],
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./index.html",
}),
new webpack.EnvironmentPlugin({ JEST_WORKER_ID: null }),
new webpack.DefinePlugin({ process: { env: {} } }),
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-react",
{ plugins: ["@babel/plugin-proposal-class-properties"] },
],
},
},
},
],
},
resolve: {
alias: { "react-native$": "react-native-web" },
extensions: [".web.js", ".js"],
},
}
```
### Web Without the Babel Plugin
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.
Ensure these hooks include a dependency array as their last argument:
- `useDerivedValue`
- `useAnimatedStyle`
- `useAnimatedProps`
- `useAnimatedReaction`
Example usage:
```javascript
const sv = useSharedValue(0)
const dv = useDerivedValue(
() => sv.value + 1,
[sv] // dependency array here
)
```
**Caution:** Pass the root dependency (`sv`) rather than `sv.value`.
Babel users must still install the `@babel/plugin-proposal-class-properties` plugin.
#### ESLint Support
To add ESLint support for Reanimated hooks, update your ESLint configuration:
```json
{
"rules": {
"react-hooks/exhaustive-deps": [
"error",
{
"additionalHooks": "(useAnimatedStyle|useDerivedValue|useAnimatedProps)"
}
]
}
}
```
**Info:** This assumes the `react-hooks` ESLint plugin is installed.
If using ESLint autofix, manually correct any `.value` additions to dependency arrays:
```javascript
const sv = useSharedValue(0)
// 🚨 bad: sv.value in array
const dv = useDerivedValue(() => sv.value, [sv.value])
// ✅ good: sv in array
const dv = useDerivedValue(() => sv.value, [sv])
```
### Solito / Next.js Compatibility
An experimental SWC plugin is being developed. Until then, follow the "Web without a Babel Plugin" instructions.
#### Next.js Polyfill
To use Reanimated with Next.js/Solito, add the `raf` polyfill for `requestAnimationFrame`:
```bash
yarn add raf
```
Include this at the top of your `_app.tsx`:
```javascript
import "raf/polyfill"
```
## React Native Reanimated: List Layout Animations (Version 3.x)
### Overview
The `itemLayoutAnimation` feature in React Native Reanimated allows you to define layout transitions for list items when their layout changes. You can choose from predefined transitions like `LinearTransition`, or create custom ones.
#### Example Usage
```typescript
import Animated, { LinearTransition } from 'react-native-reanimated';
function App() {
return (
);
}
```
### Important Notes
- **Single Column Limitation**: `itemLayoutAnimation` is only applicable to a single-column `Animated.FlatList`. The `numColumns` property must not exceed 1.
- **Dynamic Transition Changes**: You can dynamically change or disable the `itemLayoutAnimation` by setting it to `undefined`.
```typescript
import { useState } from 'react';
import Animated, { LinearTransition, JumpingTransition } from 'react-native-reanimated';
function App() {
const [transition, setTransition] = useState(LinearTransition);
const changeTransition = () => {
setTransition(
transition === LinearTransition ? JumpingTransition : LinearTransition
);
};
const toggleTransition = () => {
setTransition(transition ? undefined : LinearTransition);
};
return (
);
}
```
- **Custom Key Extractor**: If list items lack a `key` or `id` property, which are typically used by the FlatList's keyExtractor to generate unique keys for each item, you must provide your own implementation of the `keyExtractor`.
```typescript
function App() {
return (
);
}
```
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
- **Example**
- **Remarks**
- **Platform compatibility**
## Getting started
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.
### What is React Native Reanimated?
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.
### Quick Start
To begin a new project using Expo:
- **NPM**:
```bash
npx create-expo-app@latest my-app -e with-reanimated
```
- **YARN**:
```bash
yarn create expo-app my-app -e with-reanimated
```
Alternatively, explore examples available on GitHub.
### Installation
Adding Reanimated to your project involves three main steps:
#### Step 1: Install the Package
Install the `react-native-reanimated` package from npm:
- **EXPO**:
```bash
npx expo install react-native-reanimated
```
- **NPM**:
```bash
npm install react-native-reanimated
```
- **YARN**:
```bash
yarn add react-native-reanimated
```
#### Step 2: Add Reanimated's Babel Plugin
Include the `react-native-reanimated/plugin` in your `babel.config.js`:
```javascript
module.exports = {
presets: [
// existing presets
],
plugins: [
// other plugins,
"react-native-reanimated/plugin",
],
}
```
**Caution**: Ensure that `react-native-reanimated/plugin` is the last plugin listed.
#### Step 3: Wrap Metro Config with Reanimated Wrapper (Recommended)
Modify your `metro.config.js` to wrap the existing configuration using `wrapWithReanimatedMetroConfig`:
```javascript
// metro.config.js
const {
wrapWithReanimatedMetroConfig,
} = require("react-native-reanimated/metro-config")
const config = {
// Your existing Metro configuration options
}
module.exports = wrapWithReanimatedMetroConfig(config)
```
#### Step 4: Clear Metro Bundler Cache (Recommended)
- **EXPO**:
```bash
npx expo start -c
```
- **NPM**:
```bash
npm start -- --reset-cache
```
- **YARN**:
```bash
yarn start --reset-cache
```
#### Expo Development Build
For an Expo development build, update the native code in `ios` and `android` directories by running:
```bash
npx expo prebuild
```
#### Platform-Specific Setup
##### Android
No additional setup is required.
##### iOS
Before running your app on iOS, install pods with:
```bash
cd ios && pod install && cd ..
```
##### Web
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`:
- **EXPO**:
```bash
npx expo install @babel/plugin-proposal-export-namespace-from
```
- **NPM**:
```bash
npm install @babel/plugin-proposal-export-namespace-from
```
- **YARN**:
```bash
yarn add @babel/plugin-proposal-export-namespace-from
```
Ensure your `babel.config.js` includes:
```javascript
module.exports = {
presets: [
// existing presets
],
plugins: [
"@babel/plugin-proposal-export-namespace-from",
"react-native-reanimated/plugin",
],
}
```
**Note**: The `react-native-reanimated/plugin` should be listed last.
For more advanced scenarios, such as using Reanimated with `webpack` or `Next.js`, refer to the separate Web Support guide.
## useScrollViewOffset Hook
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.
### Reference
```typescript
import { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
const scrollOffset = useScrollViewOffset(animatedRef);
return (
{/* Content goes here */}
);
}
```
#### Arguments
##### `animatedRef`
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.
##### `initialRef` (Optional)
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.
#### Returns
The hook returns a shared value representing the current offset of the `ScrollView`.
### Example Usage
- The `animatedRef` argument can be dynamically changed, and the hook will continue to provide accurate values based on the connected `ScrollView`. For instance:
```typescript
useScrollViewOffset(someState ? someScrollRefA : someScrollRefB)
```
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Getting started
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.
### What is React Native Reanimated?
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.
### Quick Start
To begin a new project using Expo:
- **NPM**:
```bash
npx create-expo-app@latest my-app -e with-reanimated
```
- **YARN**:
```bash
yarn create expo-app my-app -e with-reanimated
```
Alternatively, explore examples available on GitHub.
### Installation
Adding Reanimated to your project involves three main steps:
#### Step 1: Install the Package
Install the `react-native-reanimated` package from npm:
- **EXPO**:
```bash
npx expo install react-native-reanimated
```
- **NPM**:
```bash
npm install react-native-reanimated
```
- **YARN**:
```bash
yarn add react-native-reanimated
```
#### Step 2: Add Reanimated's Babel Plugin
Include the `react-native-reanimated/plugin` in your `babel.config.js`:
```javascript
module.exports = {
presets: [
// existing presets
],
plugins: [
// other plugins,
"react-native-reanimated/plugin",
],
}
```
**Caution**: Ensure that `react-native-reanimated/plugin` is the last plugin listed.
#### Step 3: Wrap Metro Config with Reanimated Wrapper (Recommended)
Modify your `metro.config.js` to wrap the existing configuration using `wrapWithReanimatedMetroConfig`:
```javascript
// metro.config.js
const {
wrapWithReanimatedMetroConfig,
} = require("react-native-reanimated/metro-config")
const config = {
// Your existing Metro configuration options
}
module.exports = wrapWithReanimatedMetroConfig(config)
```
#### Step 4: Clear Metro Bundler Cache (Recommended)
- **EXPO**:
```bash
npx expo start -c
```
- **NPM**:
```bash
npm start -- --reset-cache
```
- **YARN**:
```bash
yarn start --reset-cache
```
#### Expo Development Build
For an Expo development build, update the native code in `ios` and `android` directories by running:
```bash
npx expo prebuild
```
#### Platform-Specific Setup
##### Android
No additional setup is required.
##### iOS
Before running your app on iOS, install pods with:
```bash
cd ios && pod install && cd ..
```
##### Web
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`:
- **EXPO**:
```bash
npx expo install @babel/plugin-proposal-export-namespace-from
```
- **NPM**:
```bash
npm install @babel/plugin-proposal-export-namespace-from
```
- **YARN**:
```bash
yarn add @babel/plugin-proposal-export-namespace-from
```
Ensure your `babel.config.js` includes:
```javascript
module.exports = {
presets: [
// existing presets
],
plugins: [
"@babel/plugin-proposal-export-namespace-from",
"react-native-reanimated/plugin",
],
}
```
**Note**: The `react-native-reanimated/plugin` should be listed last.
For more advanced scenarios, such as using Reanimated with `webpack` or `Next.js`, refer to the separate Web Support guide.
## withSpring
`withSpring` enables the creation of spring-based animations in your application.
### Reference
```typescript
import { withSpring } from "react-native-reanimated"
function App() {
sv.value = withSpring(0)
// ...
}
```
#### Arguments
##### `toValue`
The target value where the animation will settle. Supported categories include:
- **Numbers**: Can be a number or a string representation of a number.
- **Suffixed Numbers**: Strings that combine numbers and units (e.g., `"5.5%"`, `"90deg"`) without spaces, using basic English letters for suffixes.
- **Colors**:
- Hexadecimal integer: e.g., `0xff1234`
- RGB: e.g., `"rgb(100, 50, 0)"`
- RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
- RGB Hexadecimal: e.g., `"#53575E"`
- HSL: e.g., `"hsl(0, 50%, 50%)"`
- Named colors: e.g., `"dodgerblue"`
- **Objects**: Objects with properties that will be animated individually.
- **Array**: Arrays of numbers where each value is animated separately.
- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for separate animation.
Note: The `toValue` must match the category of the animated shared value (e.g., animating `width` from `100px` to `50%` is not allowed).
##### `config` (Optional)
Configuration options for spring animations:
**Physics-based Spring Configuration:**
|Name|Type|Default|Description|
|-|-|-|-|
|mass (optional)|`number`|1|The weight of the spring. Lower values make the animation faster.|
|damping (optional)|`number`|10|Controls how quickly a spring slows down; higher values result in quicker rest.|
**Duration-based Spring Configuration:**
|Name|Type|Default|Description|
|-|-|-|-|
|duration (optional)|`number`|2000|Length of the animation in milliseconds. Available in Reanimated ≥ 3.2.x.|
|dampingRatio (optional)|`number`|0.5|Determines how damped the spring is; `1` means critically damped, and values >1 mean overdamped. Available in Reanimated ≥ 3.2.x.|
**Note**: The `mass` and `damping` properties cannot be used simultaneously with `duration` and `dampingRatio`. When both are provided, `duration` and `dampingRatio` take precedence.
**Common Spring Configuration:**
|Name|Type|Default|Description|
|-|-|-|-|
|stiffness (optional)|`number`|100|Determines the bounciness of the spring.|
|velocity (optional)|`number`|0|Initial velocity applied to the spring equation.|
|overshootClamping (optional)|`boolean`|false|Prevents the spring from bouncing over the `toValue`.|
|restDisplacementThreshold (optional)|`number`|0.01|Displacement below which the spring will settle at `toValue`.|
|restSpeedThreshold (optional)|`number`|2|Speed threshold in pixels per second for settling at `toValue`.|
|reduceMotion (optional)|`ReduceMotion`|`ReduceMotion.System`|Determines animation response to reduced motion settings. Available in Reanimated ≥ 3.5.x.|
|clamp (optional)|`[number, number]`|`undefined`|Limits the movement scope; reduces bounciness if exceeded. Available in Reanimated ≥ 3.6.x.|
##### `callback` (Optional)
A function executed upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
#### Returns
`withSpring` returns an animation object representing the current state of the animation. This can be directly assigned to a shared value or used in a style object from `useAnimatedStyle`.
### Example
### Remarks
- The callback provided as the third argument is automatically workletized and executed on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useAnimatedRef
The `useAnimatedRef` hook provides a way to obtain a reference to a view, which can be used in conjunction with functions like `measure`, `scrollTo`, and `useScrollViewOffset`.
To utilize this hook, you must assign the object created by `useAnimatedRef` to the `ref` property of a component.
### Reference
```typescript
import { useAnimatedRef } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
return ;
}
```
#### Arguments
The `useAnimatedRef` hook does not accept any arguments.
#### Returns
This hook returns an object with a `current` property, which holds an instance of the component.
### Example
Here is a complete example:
```typescript
export default function App() {
const animatedRef = useAnimatedRef();
return (
{
// Access the component reference
const component = animatedRef.current;
}}
/>
);
}
```
### Remarks
- `useAnimatedRef` can be used to reference not only Animated components but any React Native component.
- The value in the `current` property is available after the component has been mounted.
```typescript
function App() {
const animatedRef = useAnimatedRef();
console.log(animatedRef.current); // 🚩 Returns null
useEffect(() => {
console.log(animatedRef.current); // ✅ Returns the component
}, []);
return ;
}
```
Alternatively, you can access the value in `current` through event handlers or the `onLayout` property.
- The value stored in the `current` property is not available on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Web Support
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.
### Step 1: Install the Package
Install `@babel/plugin-proposal-export-namespace-from` using one of the following package managers:
- **EXPO**
```bash
npx expo install @babel/plugin-proposal-export-namespace-from
```
- **NPM**
```bash
npm install @babel/plugin-proposal-export-namespace-from
```
- **YARN**
```bash
yarn add @babel/plugin-proposal-export-namespace-from
```
### Step 2: Add Plugins to Config File
Update your `babel.config.js` by adding the following plugins:
```javascript
module.exports = {
presets: [
// Existing presets...
],
plugins: [
...,
'@babel/plugin-proposal-export-namespace-from',
'react-native-reanimated/plugin', // Ensure this is listed last
],
};
```
**Caution:** Make sure `react-native-reanimated/plugin` is the last plugin in the list.
### Step 3: Launch Your App
To start a playground app in the browser, use:
```bash
yarn web
```
For example applications from the Reanimated repository, execute these commands at the root of the repository:
```bash
yarn && yarn build
```
Then navigate to `apps/web-example` and run:
```bash
yarn start
```
### Webpack Support
To use Reanimated in a Webpack app, adjust your configuration as follows:
Example Webpack config with Reanimated support:
```javascript
const HtmlWebpackPlugin = require("html-webpack-plugin")
const webpack = require("webpack")
module.exports = {
entry: ["babel-polyfill", "./index.js"],
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./index.html",
}),
new webpack.EnvironmentPlugin({ JEST_WORKER_ID: null }),
new webpack.DefinePlugin({ process: { env: {} } }),
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-react",
{ plugins: ["@babel/plugin-proposal-class-properties"] },
],
},
},
},
],
},
resolve: {
alias: { "react-native$": "react-native-web" },
extensions: [".web.js", ".js"],
},
}
```
### Web Without the Babel Plugin
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.
Ensure these hooks include a dependency array as their last argument:
- `useDerivedValue`
- `useAnimatedStyle`
- `useAnimatedProps`
- `useAnimatedReaction`
Example usage:
```javascript
const sv = useSharedValue(0)
const dv = useDerivedValue(
() => sv.value + 1,
[sv] // dependency array here
)
```
**Caution:** Pass the root dependency (`sv`) rather than `sv.value`.
Babel users must still install the `@babel/plugin-proposal-class-properties` plugin.
#### ESLint Support
To add ESLint support for Reanimated hooks, update your ESLint configuration:
```json
{
"rules": {
"react-hooks/exhaustive-deps": [
"error",
{
"additionalHooks": "(useAnimatedStyle|useDerivedValue|useAnimatedProps)"
}
]
}
}
```
**Info:** This assumes the `react-hooks` ESLint plugin is installed.
If using ESLint autofix, manually correct any `.value` additions to dependency arrays:
```javascript
const sv = useSharedValue(0)
// 🚨 bad: sv.value in array
const dv = useDerivedValue(() => sv.value, [sv.value])
// ✅ good: sv in array
const dv = useDerivedValue(() => sv.value, [sv])
```
### Solito / Next.js Compatibility
An experimental SWC plugin is being developed. Until then, follow the "Web without a Babel Plugin" instructions.
#### Next.js Polyfill
To use Reanimated with Next.js/Solito, add the `raf` polyfill for `requestAnimationFrame`:
```bash
yarn add raf
```
Include this at the top of your `_app.tsx`:
```javascript
import "raf/polyfill"
```
## runOnJS
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.
`runOnJS` is commonly used to update React state either after an animation completes or conditionally within a gesture interaction.
### Reference
```typescript
import { runOnJS } from "react-native-reanimated"
function App() {
// Executing on the UI thread
runOnJS(navigation.goBack)()
}
```
#### Arguments
##### `fn`
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);`.
#### Returns
`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.
**Note:** Ensure you call the function returned from `runOnJS`.
### Example
### Remarks
- 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:
```typescript
withTiming(0, {}, () => {
// myFunction is defined on the UI thread 🚨
const myFunction = () => {
// ...
}
runOnJS(myFunction)() // 💥
})
```
- A common mistake is to execute a function inside `runOnJS` like this: ~~`runOnJS(setValue(10))()`~~. The correct usage would be `runOnJS(setValue)(10)`.
- It's safe to run functions via `runOnJS` on the JavaScript thread, as it has no adverse effects.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## withTiming
`withTiming` enables you to create animations based on duration and easing functions.
### Reference
```typescript
import { withTiming } from "react-native-reanimated"
function App() {
sv.value = withTiming(0)
// ...
}
```
#### Arguments
##### `toValue`
The target value for the animation. Supported categories include:
- **Numbers**: Can be a number or a string representation of a number.
- **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.
- **Colors**:
- Hexadecimal integer: e.g., `0xff1234`
- RGB: e.g., `"rgb(100, 50, 0)"`
- RGBA: e.g., `"rgba(255, 105, 180, 0.5)"`
- RGB Hexadecimal: e.g., `"#53575E"`
- HSL: e.g., `"hsl(0, 50%, 50%)"`
- Named colors: e.g., `"dodgerblue"`
- **Objects**: Objects with properties that will be animated individually.
- **Arrays**: Arrays of numbers where each value is animated separately.
- **Transformation Matrix**: An array of exactly 16 numerical values treated as a transformation matrix, decomposed into rotation, scale, and translation for animation.
Ensure `toValue` and the shared value being animated are of the same category (e.g., you cannot animate `width` from `100px` to `50%`).
##### `config` (Optional)
The configuration for timing animations. Available properties:
|Name|Type|Default|Description|
|-|-|-|-|
|duration|`number`|300|Length of the animation in milliseconds.|
|easing|`Easing`|`Easing.inOut(Easing.quad)`|An easing function defining the animation curve.|
|reduceMotion|`ReduceMotion`|`ReduceMotion.System`|Determines how the animation responds to reduced motion settings on devices.|
###### `Easing`
The `easing` parameter allows fine-tuning of the animation over time, such as starting with fast acceleration and slowing down towards the end.
Reanimated provides various easing functions in the `Easing` module. You can visualize common easing functions at [easings.net](http://easings.net/).
Use built-in easings by passing them to the `withTiming` config:
```typescript
import { Easing } from "react-native-reanimated"
withTiming(sv.value, {
easing: Easing.bounce,
})
```
Available functions include:
- `back`: Animation where the object slightly moves back before moving forward.
- `bezier(x1: number, y1: number, x2: number, y2: number)`: Cubic bezier curve.
- `bounce`: Bouncing animation.
- `circle`: Circular function.
- `cubic`: Cubic function.
- `ease`: Simple inertial animation.
- `elastic(bounciness?: number)`: Spring interaction.
- `exp`: Exponential function.
- `linear`: Linear function.
- `poly(n: number)`: Higher power functions like quartic, quintic.
- `quad`: Quadratic function.
- `sin`: Sinusoidal function.
Helpers to modify easing functions:
- `in(easing: EasingFunction)`: Runs an easing function forwards.
- `inOut(easing: EasingFunction)`: Symmetrical easing function.
- `out(easing: EasingFunction)`: Runs an easing function backwards.
##### `callback` (Optional)
A function called upon animation completion. If the animation is canceled, it receives `false`; otherwise, it receives `true`.
#### Returns
`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`.
### Example
### Remarks
- The callback passed as the third argument is automatically workletized and executed on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Animating styles and props
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`.
### Animating Styles
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.
```typescript
import Animated, { useSharedValue } from 'react-native-reanimated';
function App() {
const width = useSharedValue(100);
return ;
}
```
For example, multiplying a shared value before assigning it to the `style` prop is not possible:
```typescript
// This won't work
```
Consider an example where a box moves right on button press:
```typescript
import { View, Button } from 'react-native';
import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
function App() {
const translateX = useSharedValue(0);
const handlePress = () => {
translateX.value = withSpring(translateX.value + 50);
};
return (
);
}
```
To customize shared value changes based on user input, `useAnimatedStyle` is used for more control and flexibility:
```typescript
export default function App() {
const translateX = useSharedValue(0);
const handlePress = () => {
translateX.value += 50;
};
const animatedStyles = useAnimatedStyle(() => ({
transform: [{ translateX: withSpring(translateX.value * 2) }],
}));
return (
<>
>
);
}
```
`useAnimatedStyle` allows access to the shared value's `.value`, enabling operations like multiplication before assigning it to `style`. It also centralizes animation logic.
### Animating Props
While many values are animated via the `style` property, sometimes props need animating. For example, SVG elements use props instead of styles:
```typescript
```
To animate non-Reanimated components' props, wrap them with `createAnimatedComponent`:
```typescript
import Animated from "react-native-reanimated"
import { Circle } from "react-native-svg"
const AnimatedCircle = Animated.createAnimatedComponent(Circle)
```
Animating the radius of an SVG circle can be done by passing a shared value as a prop:
```typescript
import { useSharedValue } from 'react-native-reanimated';
import { Svg } from 'react-native-svg';
function App() {
const r = useSharedValue(10);
return (
);
}
```
For encapsulating animation logic and accessing `.value`, `useAnimatedProps` is used:
```typescript
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
export default function App() {
const r = useSharedValue(20);
const handlePress = () => {
r.value += 10;
};
const animatedProps = useAnimatedProps(() => ({
r: withTiming(r.value),
}));
return (
);
}
```
In `useAnimatedProps`, return an object with animatable props, then pass it to the `animatedProps` prop of an Animated component.
### Summary
- Inline styles are simple but limited for complex animations.
- Props differ from styles as they aren't passed via the `style` object.
- `useAnimatedStyle` and `useAnimatedProps` provide access to shared values' `.value`, enhancing animation control.
- Custom animatable components can be created with `Animated.createAnimatedComponent`.
### What's Next?
In the next section, we'll delve into animation functions and customizing their behavior.
## useDerivedValue
The `useDerivedValue` function allows for the creation of new reactive shared values derived from existing ones. This ensures that any changes in the original shared values automatically update the derived value.
### Reference
```typescript
import { useDerivedValue } from "react-native-reanimated"
function App() {
const derivedValue = useDerivedValue(() => {
return sv.value * 50
})
}
```
#### Arguments
##### `updater`
A function that returns a new value constructed using shared values, React state, or other JavaScript values. This function is invoked whenever any of the shared values or states it depends on change.
##### `dependencies` (Optional)
An optional array specifying dependencies. This parameter is only relevant when Reanimated is used without its Babel plugin in web environments.
#### Returns
The `useDerivedValue` function returns a new, readonly shared value that reflects changes based on the output of the `updater` function.
### Example
### Remarks
- The callback provided to the first argument is automatically workletized and executed on the UI thread.
- You can use `useDerivedValue` without returning a value in the `updater` function to respond to changes in a shared value. For accessing previous values stored in a shared value, consider using `useAnimatedReaction`.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## runOnUI
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.
### Reference
```typescript
import { runOnUI } from "react-native-reanimated"
function App() {
// Example usage in an event handler or effect
runOnUI((greeting: string) => {
console.log(`${greeting} from the UI thread`)
})("Howdy")
// ...
}
```
#### Arguments
##### fn
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)`.
#### Returns
`runOnUI` returns a function that accepts arguments for the initially provided function.
**Note:** Ensure you invoke the function returned from `runOnUI`.
### Example
### Remarks
- 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.
- 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)`.
- The callback provided as an argument is automatically workletized, making it ready for execution on the UI thread.
- Avoid executing `runOnUI` directly on the UI thread to prevent errors.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## runOnRuntime
The `runOnRuntime` function allows you to execute workletized functions asynchronously on a separate worklet runtime, which operates on a different thread.
### Reference
```typescript
import { createWorkletRuntime, runOnRuntime } from "react-native-reanimated"
const workletRuntime = createWorkletRuntime("background")
function App() {
// Example usage in an event handler or effect
runOnRuntime(workletRuntime, (greeting) => {
console.log(`${greeting} from a separate thread`)
})("Howdy")
// ...
}
```
#### Arguments
##### workletRuntime
A reference to the worklet runtime created using `createWorkletRuntime`.
##### fn
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)`.
#### Returns
`runOnRuntime` returns a function that accepts arguments for the function provided as its first argument.
**Note:** Ensure you call the function returned from `runOnRuntime`.
### Remarks
- A common mistake is to execute a function inside of `runOnRuntime` incorrectly, such as: ~~`runOnRuntime(myWorklet(10))()`~~. The correct usage is `runOnRuntime(myWorklet)(10)`.
- 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.
- `runOnRuntime` can be called on any runtime, including the RN runtime, UI runtime, and other worklet runtimes.
- 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.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|❌|
## Applying modifiers
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.
### Starting Point
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.
```typescript
export default function App() {
const offset = useSharedValue(0);
const style = useAnimatedStyle(() => ({
transform: [{ translateX: offset.value }],
}));
const OFFSET = 40;
const handlePress = () => {
offset.value = withTiming(OFFSET);
};
return (
);
}
```
### Repeating an Animation
To create a shake effect, use the `withRepeat` modifier. This allows you to repeat an animation multiple times or indefinitely.
```typescript
import { withRepeat } from "react-native-reanimated"
function App() {
sv.value = withRepeat(withTiming(50), 5)
}
```
Pass a number for repetitions or a non-positive value for infinite repetition. Use `true` as the third argument to reverse the animation direction.
Updated example:
```typescript
export default function App() {
const offset = useSharedValue(0);
const style = useAnimatedStyle(() => ({
transform: [{ translateX: offset.value }],
}));
const OFFSET = 40;
const handlePress = () => {
offset.value = withRepeat(withTiming(OFFSET), 5, true);
};
return (
);
}
```
### Running Animations in a Sequence
To enhance the animation, use `withSequence` to chain animations. This modifier starts the next animation when the previous one ends.
```typescript
import { withSequence } from "react-native-reanimated"
function App() {
sv.value = withSequence(withTiming(50), withTiming(0))
}
```
Improved example:
```typescript
const TIME = 250
const handlePress = () => {
offset.value = withSequence(
// start from -OFFSET
withTiming(-OFFSET, { duration: TIME / 2 }),
// shake between -OFFSET and OFFSET 5 times
withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
// go back to 0 at the end
withTiming(0, { duration: TIME / 2 })
)
}
```
### Starting the Animation with Delay
Add suspense by delaying the animation start using `withDelay`.
```typescript
import { withDelay } from "react-native-reanimated"
function App() {
sv.value = withDelay(500, withTiming(0))
}
```
Final example:
```typescript
const OFFSET = 40
const TIME = 250
const DELAY = 400
const handlePress = () => {
offset.value = withDelay(
DELAY,
withSequence(
// start from -OFFSET
withTiming(-OFFSET, { duration: TIME / 2 }),
// shake between -OFFSET and OFFSET 5 times
withRepeat(withTiming(OFFSET, { duration: TIME }), 5, true),
// go back to 0 at the end
withTiming(0, { duration: TIME / 2 })
)
)
}
```
### Summary
- **Modifiers**: `withRepeat`, `withSequence`, and `withDelay`.
- **`withRepeat`**: Repeats an animation a specified number of times or indefinitely.
- **`withSequence`**: Chains animations to run sequentially.
- **`withDelay`**: Delays the start of an animation.
### What's Next?
Explore handling `Tap` and `Pan` gestures, and learn about the `withDecay` animation function.
## withDecay
The `withDecay` function allows you to create animations that simulate objects moving under friction. These animations begin at a specified velocity and gradually slow down according to the provided deceleration rate until they come to a stop.
### Reference
```typescript
import { withDecay } from "react-native-reanimated"
function App() {
sv.value = withDecay({ velocity: 1 })
// ...
}
```
#### Arguments
##### `config`
Configuration for the decay animation. The following properties are available:
|Name|Type|Default|Description|
|-|-|-|-|
|`velocity` (optional)|`number`|0|Initial velocity of the animation.|
|`deceleration` (optional)|`number`|0.998|Rate at which the velocity decreases over time.|
|`clamp` (optional)\*|`[number, number]`|\[]|Array specifying bounds to restrict the animation's range. The animation stops when either bound is reached unless `rubberBandEffect` is set to `true`. \*Required if `rubberBandEffect` is enabled.|
|`velocityFactor` (optional)|`number`|1|Multiplier for velocity.|
|`rubberBandEffect` (optional)|`boolean`|false|Enables bouncing over the limit specified in `clamp`.|
|`rubberBandFactor` (optional)|`number`|0.6|Determines the strength of the rubber band effect.|
|`reduceMotion` (optional)|`ReduceMotion`|`ReduceMotion.System`|Controls how the animation responds to the device's reduced motion accessibility setting.|
##### `callback` (Optional)
A function executed upon animation completion. If the animation is canceled, the callback receives `false`; otherwise, it receives `true`.
#### Returns
The `withDecay` function returns an animation object representing the current state of the animation. This object can be directly assigned to a shared value or used as a style object returned from `useAnimatedStyle`.
### Example
*Note: An example section is mentioned but not provided in the original content.*
### Remarks
- The callback passed as the second argument is automatically workletized and executed on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## createAnimatedComponent
The `createAnimatedComponent` function enables the creation of an Animated version of any React Native component. By wrapping a component with `createAnimatedComponent`, Reanimated can animate any prop or style associated with that component.
Reanimated includes five built-in Animated components:
- `Animated.FlatList`
- `Animated.Image`
- `Animated.View`
- `Animated.ScrollView`
- `Animated.Text`
To animate other React Native components, they must be wrapped using the `createAnimatedComponent` function.
### Reference
```typescript
import Animated from "react-native-reanimated"
import { TextInput } from "react-native"
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput)
```
#### Arguments
##### `component`
The component you wish to make animatable. Function components must be wrapped with `React.forwardRef()`.
#### Returns
`createAnimatedComponent` returns a component that Reanimated can animate.
### Example
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## createWorkletRuntime
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.
### Reference
#### Usage in JavaScript
```typescript
import { createWorkletRuntime } from "react-native-reanimated"
function App() {
const runtime = createWorkletRuntime("background")
}
```
#### Usage in C++
```cpp
auto runtime = reanimated::extractWorkletRuntime(rt, runtimeValue);
jsi::Runtime &rt = runtime->getJSIRuntime();
auto worklet = reanimated::extractShareableOrThrow(rt, workletValue);
runtime->runGuarded(worklet, ...args);
```
#### Arguments
- **`name`**: A string identifier for the runtime that will appear in device lists within Chrome DevTools.
- **`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.
#### Returns
The `createWorkletRuntime` function returns a `WorkletRuntime`, which is represented as a `jsi::HostObject`.
### Remarks
- 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.
- 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.
- 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`.
- 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.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|❌|
## interpolate
The `interpolate` function is used to map a numeric value from one specified range to another using linear interpolation.
### Reference Usage
```typescript
import { interpolate, Extrapolation } from "react-native-reanimated"
function App() {
const animatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(sv.value, [0, 100], [0, 1], Extrapolation.CLAMP),
}))
}
```
#### Parameters
- **`value`**: A numeric value that will be mapped to the specified `output` range.
- **`input`**: An array of numbers defining the input range for interpolation.
- **`output`**: An array of numbers defining the output range for interpolation, which should have at least as many points as the input range.
- **`extrapolate` (Optional)**: Determines behavior when `value` is outside the `input` range. Defaults to `Extrapolation.EXTEND`.
Available options:
- `Extrapolation.EXTEND`: Predicts values beyond the output range.
- `Extrapolation.CLAMP`: Clamps the value to the edge of the output range.
- `Extrapolation.IDENTITY`: Returns the provided value unchanged.
String equivalents include `"extend"`, `"clamp"`, and `"identity"`.
To apply extrapolation to a specific edge, use an object:
```typescript
const opacity = interpolate(sv.value, [0, 100], [0, 1], {
extrapolateLeft: Extrapolation.CLAMP,
})
```
#### Return Value
The `interpolate` function returns a value mapped within the specified output range.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## cancelAnimation
The `cancelAnimation` function is used to stop an ongoing animation associated with a shared value in React Native Reanimated.
### Reference
```typescript
import { cancelAnimation } from "react-native-reanimated"
function App() {
const offset = useSharedValue(100)
const handleCancel = () => {
cancelAnimation(offset)
}
}
```
#### Arguments
- **`sharedValue`**: This is the shared value linked to an active animation that you wish to terminate. If no animation is currently running, `cancelAnimation` will have no effect.
#### Returns
The function returns `undefined`.
### Example Usage
To cancel an ongoing animation, simply call `cancelAnimation` with the relevant shared value as shown in the reference section above.
### Remarks
- You can restart a canceled animation by reassigning it to the same shared value using functions like `withSpring` or `withTiming`.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This function is compatible across Android, iOS, and web platforms.
## Clamp Function in React Native Reanimated
The `clamp` function is used to restrict a value within a specified range, ensuring it does not exceed the defined minimum and maximum bounds.
### Reference
```typescript
import { clamp } from "react-native-reanimated"
function App() {
const result = clamp(sv.value, 0, 100)
}
```
#### Arguments
- **`value`**: A numeric value that will be returned if it falls within the specified `min` and `max` range.
- **`min`**: The lower bound. If the provided `value` is less than this number, `min` will be returned.
- **`max`**: The upper bound. If the provided `value` exceeds this number, `max` will be returned.
#### Returns
The function returns a numeric value that lies between the specified `min` and `max` bounds.
### Example Usage
```typescript
import { clamp } from "react-native-reanimated"
function App() {
const constrainedValue = clamp(150, 0, 100) // Result will be 100
}
```
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This function is compatible across Android, iOS, and Web platforms.
## interpolateColor
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.
### Reference Example
```typescript
import { interpolateColor } from 'react-native-reanimated';
function App() {
const progress = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => {
return {
backgroundColor: interpolateColor(
progress.value,
[0, 1],
['red', 'green']
),
};
});
// ...
return ;
}
```
#### Arguments
- **`value`**: A number from the input range that is mapped to the output range.
- **`input`**: An array of numbers specifying the input range for interpolation. The values should be in increasing order.
- **`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.
- **`colorSpace`** *(Optional)*: Specifies the color space for interpolation, either `'HSV'` or `'RGB'`. Defaults to `'RGB'`.
- **`options`** *(Optional)*: Additional parameters for color interpolation:
|Options|Type|Default|Description|
|-|-|-|-|
|`gamma`|`number`|2.2|Gamma parameter used in gamma correction.|
|`useCorrectedHSVInterpolation`|`boolean`|true|Reduces the number of hues during interpolation by treating HSV as circular.|
#### Options Explanation
- **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.
- **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).
#### Returns
The function returns an interpolated color in `rgba(r, g, b, a)` format within the specified output range.
### Remarks
- The function operates similarly to the `interpolate` function but specifically outputs a color string in `rgba(r, g, b, a)` notation.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This function is versatile and compatible across major platforms, making it ideal for cross-platform applications.
## withSequence
`withSequence` is an animation modifier that allows animations to be executed in a sequential order.
### Reference
```typescript
import { withSequence } from "react-native-reanimated"
function App() {
sv.value = withSequence(withTiming(50), withTiming(0))
// ...
}
```
#### Arguments
##### `reduceMotion` (Optional)
A parameter that specifies how the animation should respond to the device's reduced motion accessibility setting.
##### `...animations`
Any number of animation objects that will be executed in sequence.
#### Returns
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`.
### Example
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## scrollTo
The `scrollTo` function allows you to synchronously scroll a component to a specified X or Y offset.
### Reference
```typescript
import { scrollTo } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
const scrollY = useSharedValue(0);
useDerivedValue(() => {
scrollTo(animatedRef, 0, scrollY.value, true);
});
return (
{/* ... */}
);
}
```
#### Arguments
- **`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.
- **`x`**: The pixel value for horizontal scrolling on the X axis.
- **`y`**: The pixel value for vertical scrolling on the Y axis.
- **`animated`**: A boolean indicating if the scroll should be smooth (`true`) or instant (`false`).
#### Returns
The `scrollTo` function returns `undefined`.
### Remarks
- The `scrollTo` function must be invoked from the UI thread.
- It supports `Animated.FlatList`.
- Typically works with other ScrollView-like and FlatList-like components if they use a `ScrollView` internally and are animated.
- Scrollable components need to implement the `getScrollableNode` method (and `getNativeScrollRef` for New Architecture) to be compatible with `scrollTo`.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## getRelativeCoords Functionality
The `getRelativeCoords` function is used to determine the screen location relative to a specified view.
### Reference Code
```typescript
import { getRelativeCoords } from 'react-native-reanimated';
const Comp = () => {
const animatedRef = useAnimatedRef();
const gestureHandler = useAnimatedGestureHandler({
onEnd: (event) => {
const coords = getRelativeCoords(
animatedRef,
event.absoluteX,
event.absoluteY
);
},
});
return (
);
};
```
### Arguments
- **`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.
- **`absoluteX`**: A number representing the absolute x-coordinate.
- **`absoluteY`**: A number representing the absolute y-coordinate.
### Returns
An object containing:
- `x`: The relative x-coordinate.
- `y`: The relative y-coordinate.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useAnimatedGestureHandler
**Warning:**\
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.
This hook necessitates that `react-native-gesture-handler` be installed and configured within your project.
### Reference
```typescript
import { useAnimatedGestureHandler } from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';
function App() {
const x = useSharedValue(0);
const gestureHandler = useAnimatedGestureHandler({
onStart: (_, ctx) => {
ctx.startX = x.value;
},
onActive: (event, ctx) => {
x.value = ctx.startX + event.translationX;
},
});
return (
);
}
```
#### Arguments
##### `gestureHandlers`
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`.
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:
- `event` \[object] - an event object containing the payload specific to the type of gesture handler (e.g., `PanGestureHandler`, `RotationGestureHandler`).
- `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.
##### `dependencies` (Optional)
An optional array of dependencies is relevant only when using Reanimated without the Babel plugin on the Web.
#### Returns
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.
### Example
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|⚠️|
- On the Web, it is necessary to pass the returned handler object to both `onGestureEvent` and `onHandlerStateChange` parameters.
## useScrollViewOffset Hook
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.
### Reference
```typescript
import { useAnimatedRef, useScrollViewOffset } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
const scrollOffset = useScrollViewOffset(animatedRef);
return (
{/* Content goes here */}
);
}
```
#### Arguments
##### `animatedRef`
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.
##### `initialRef` (Optional)
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.
#### Returns
The hook returns a shared value representing the current offset of the `ScrollView`.
### Example Usage
- The `animatedRef` argument can be dynamically changed, and the hook will continue to provide accurate values based on the connected `ScrollView`. For instance:
```typescript
useScrollViewOffset(someState ? someScrollRefA : someScrollRefB)
```
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## measure
The `measure` function allows you to synchronously obtain the dimensions and position of a view on the screen, executed on the UI thread.
### Reference
```typescript
import { measure } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
const handlePress = () => {
runOnUI(() => {
const measurement = measure(animatedRef);
if (measurement === null) {
return;
}
// Additional logic can be added here
})();
};
return ;
}
```
#### Arguments
- **`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.
#### Returns
The `measure` function returns an object containing:
|Field|Description|
|-|-|
|`x`|A number representing the X coordinate relative to the parent component.|
|`y`|A number representing the Y coordinate relative to the parent component.|
|`width`|A number representing the width of the component.|
|`height`|A number representing the height of the component.|
|`pageX`|A number representing the X coordinate relative to the screen.|
|`pageY`|A number representing the Y coordinate relative to the screen.|
Alternatively, it returns `null` if the measurement could not be performed.
### Remarks
- **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.
- **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:
```typescript
function App() {
const animatedStyles = useAnimatedStyle(() => {
if (_WORKLET) {
// Safely use measure here
const measurement = measure(animatedRef)
}
})
}
```
- **Consecutive Runs**: Subsequent executions of `useAnimatedStyle` occur on the UI thread.
- **Alternative for Static Dimensions**: If only static dimensions are needed and measurements aren't used during animations, consider using the `onLayout` property instead.
- **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:
```typescript
const animatedRef = useAnimatedRef()
const handlePress = () => {
runOnUI(() => {
const measurement = measure(animatedRef)
if (measurement === null) {
return
}
// Additional logic can be added here
})()
}
```
- **Rendered Components Only**: `measure` is applicable only to rendered components. For example, measuring off-screen items in a `FlatList` will yield `null`.
- **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.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useAnimatedReaction
The `useAnimatedReaction` hook enables responses to changes in shared values, particularly useful when comparing previous and current values stored within a shared value.
### Reference
```typescript
import { useAnimatedReaction } from "react-native-reanimated"
function App() {
useAnimatedReaction(
() => sv.value,
(currentValue, previousValue) => {
if (currentValue !== previousValue) {
// perform an action ✨
}
}
)
// ...
}
```
#### Arguments
##### `prepare`
A function returning the value to which you want to react. This returned value serves as the first parameter for the `react` argument.
```typescript
function App() {
useAnimatedReaction(
() => Math.floor(sv.value),
(currentValue, previousValue) => {
// ...
}
)
}
```
##### `react`
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`.
```typescript
function App() {
useAnimatedReaction(
() => Math.floor(sv.value),
(currentValue, previousValue) => {
// ...
}
)
}
```
##### `dependencies` (Optional)
An optional array of dependencies. This is only relevant when using Reanimated without the Babel plugin on the Web.
#### Returns
The `useAnimatedReaction` hook returns `undefined`.
### Example
### Remarks
- Avoid mutating the same shared value in the `react` function that was used in the `prepare` function to prevent infinite loops.
```typescript
function App() {
useAnimatedReaction(
() => width.value,
(currentValue) => {
// 🚨 An infinite loop!
width.value += currentValue
}
)
}
```
- Callbacks for both `prepare` and `react` are automatically workletized, running on the UI thread.
- While you can use `useAnimatedReaction` to react to any stateful React value, it's generally better to use a `useEffect` for such purposes.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Animating styles and props
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`.
### Animating Styles
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.
```typescript
import Animated, { useSharedValue } from 'react-native-reanimated';
function App() {
const width = useSharedValue(100);
return ;
}
```
For example, multiplying a shared value before assigning it to the `style` prop is not possible:
```typescript
// This won't work
```
Consider an example where a box moves right on button press:
```typescript
import { View, Button } from 'react-native';
import Animated, { useSharedValue, withSpring } from 'react-native-reanimated';
function App() {
const translateX = useSharedValue(0);
const handlePress = () => {
translateX.value = withSpring(translateX.value + 50);
};
return (
);
}
```
To customize shared value changes based on user input, `useAnimatedStyle` is used for more control and flexibility:
```typescript
export default function App() {
const translateX = useSharedValue(0);
const handlePress = () => {
translateX.value += 50;
};
const animatedStyles = useAnimatedStyle(() => ({
transform: [{ translateX: withSpring(translateX.value * 2) }],
}));
return (
<>
>
);
}
```
`useAnimatedStyle` allows access to the shared value's `.value`, enabling operations like multiplication before assigning it to `style`. It also centralizes animation logic.
### Animating Props
While many values are animated via the `style` property, sometimes props need animating. For example, SVG elements use props instead of styles:
```typescript
```
To animate non-Reanimated components' props, wrap them with `createAnimatedComponent`:
```typescript
import Animated from "react-native-reanimated"
import { Circle } from "react-native-svg"
const AnimatedCircle = Animated.createAnimatedComponent(Circle)
```
Animating the radius of an SVG circle can be done by passing a shared value as a prop:
```typescript
import { useSharedValue } from 'react-native-reanimated';
import { Svg } from 'react-native-svg';
function App() {
const r = useSharedValue(10);
return (
);
}
```
For encapsulating animation logic and accessing `.value`, `useAnimatedProps` is used:
```typescript
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
export default function App() {
const r = useSharedValue(20);
const handlePress = () => {
r.value += 10;
};
const animatedProps = useAnimatedProps(() => ({
r: withTiming(r.value),
}));
return (
);
}
```
In `useAnimatedProps`, return an object with animatable props, then pass it to the `animatedProps` prop of an Animated component.
### Summary
- Inline styles are simple but limited for complex animations.
- Props differ from styles as they aren't passed via the `style` object.
- `useAnimatedStyle` and `useAnimatedProps` provide access to shared values' `.value`, enhancing animation control.
- Custom animatable components can be created with `Animated.createAnimatedComponent`.
### What's Next?
In the next section, we'll delve into animation functions and customizing their behavior.
## useFrameCallback in React Native Reanimated (Version: 3.x)
### Overview
The `useFrameCallback` hook allows you to execute a function on every frame update within your application.
### Reference
```typescript
import { useFrameCallback } from 'react-native-reanimated';
function App() {
const frameCallback = useFrameCallback((frameInfo) => {
// Increment a value with each frame update
sv.value += 1;
});
return (
frameCallback.setActive(!frameCallback.isActive)}
/>
);
}
```
#### Arguments
##### `callback`
- A function that runs on every frame update.
- Receives a `frameInfo` object with the following properties:
- `timestamp`: The system time (in milliseconds) when the last frame was rendered.
- `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.
- `timeSinceFirstFrame`: The time (in milliseconds) elapsed since the callback was activated.
##### `autostart` (Optional)
- Determines if the callback should start automatically. Defaults to `true`.
#### Returns
The `useFrameCallback` hook returns an object with these properties:
- `setActive`: A function to start or stop the frame callback.
- `isActive`: A boolean indicating whether the callback is currently running.
- `callbackId`: A unique identifier for the frame callback.
### Remarks
- The function provided in the `callback` argument is automatically workletized and executed on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
- Reference
- Arguments
- Returns
- Example
- Remarks
- Platform compatibility
## Handling gestures
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.
Ensure you've completed the Gesture Handler installation steps before proceeding.
### Handling Tap Gestures
We begin with tap gestures, which detect brief screen touches. These can be used for custom buttons or pressable elements.
In this example, a circle grows and changes color upon touch.
First, wrap your app in `GestureHandlerRootView` to ensure gesture functionality:
```typescript
import { GestureHandlerRootView } from 'react-native-gesture-handler';
function App() {
return (
{/* rest of the app */}
);
}
```
Define tap gestures using `Gesture.Tap()` and chain methods like `onBegin`, `onStart`, `onEnd`, or `onFinalize` to update shared values:
```typescript
export default function App() {
const pressed = useSharedValue(false);
const tap = Gesture.Tap()
.onBegin(() => {
pressed.value = true;
})
.onFinalize(() => {
pressed.value = false;
});
```
Access shared values safely as gesture callbacks are automatically workletized.
Define animation logic using `withTiming` in `useAnimatedStyle`:
```typescript
const animatedStyles = useAnimatedStyle(() => ({
backgroundColor: pressed.value ? "#FFE04B" : "#B58DF1",
transform: [{ scale: withTiming(pressed.value ? 1.2 : 1) }],
}))
```
Pass the gesture to `GestureDetector` and apply `animatedStyles`:
```typescript
return (
);
}
```
### Handling Pan Gestures
Enhance the circle by making it draggable and bouncing back to its starting position upon release. Retain color highlight and scale effects.
Switch from `Tap` to `Pan` gesture and add an `onChange` method:
```typescript
const offset = useSharedValue(0);
const pan = Gesture.Pan()
.onBegin(() => {
pressed.value = true;
})
.onChange((event) => {
offset.value = event.translationX;
})
.onFinalize(() => {
offset.value = withSpring(0);
pressed.value = false;
```
Use `translationX` from the event data to move the circle. Reset `offset.value` in `onFinalize` using `withSpring`.
Adjust `useAnimatedStyle` for handling offset:
```typescript
const animatedStyles = useAnimatedStyle(() => ({
transform: [
{ translateX: offset.value },
{ scale: withTiming(pressed.value ? 1.2 : 1) },
],
backgroundColor: pressed.value ? "#FFE04B" : "#b58df1",
}))
```
### Using `withDecay`
`withDecay` retains gesture velocity for decelerating animations.
Pass final velocity in `onFinalize` to `withDecay`:
```typescript
const pan = Gesture.Pan()
.onChange((event) => {
offset.value += event.changeX;
})
.onFinalize((event) => {
offset.value = withDecay({
velocity: event.velocityX,
rubberBandEffect: true,
clamp: [
-(width.value / 2) + SIZE / 2 + BOUNDARY_OFFSET,
width.value / 2 - SIZE / 2 - BOUNDARY_OFFSET,
```
Ensure the square stays within screen bounds.
Explore `withDecay` API for more configuration options.
### Summary
This section covered gesture handling with Reanimated and Gesture Handler, focusing on `Tap`, `Pan`, and `withDecay`. Key points include:
- Integration of Reanimated with React Native Gesture Handler.
- Creation of gestures like `Gesture.Pan()` or `Gesture.Tap()`.
- Accessing shared values in gesture callbacks without extra boilerplate.
- Using `withDecay` for decelerating animations based on gesture velocity.
### What's Next?
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.
## withRepeat
`withRepeat` is an animation modifier that allows you to repeat a specified animation a certain number of times or indefinitely.
### Reference
```typescript
import { withRepeat } from "react-native-reanimated"
function App() {
sv.value = withRepeat(withSpring(0), 5)
// ...
}
```
#### Arguments
##### `animation`
The animation object you wish to repeat.
##### `numberOfReps` (Optional)
Specifies how many times the animation should be repeated. The default is `2`.
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.
##### `reverse` (Optional)
Determines whether the animation should alternate directions with each repetition. The default setting is `false`.
This feature only supports direct animation functions like `withSpring` and does not work with other animation modifiers such as `withSequence`.
##### `callback` (Optional)
A function that executes upon the completion of the animation. If the animation is canceled, the callback receives `false`; otherwise, it receives `true`.
##### `reduceMotion` (Optional)
Controls how the animation responds to the device's reduced motion accessibility setting.
#### Returns
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`.
### Remarks
- The callback provided in the fourth argument is automatically workletized and executed on the UI thread.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## useComposedEventHandler
The `useComposedEventHandler` hook allows you to combine multiple event handlers, such as those created with `useAnimatedScrollHandler`, into a single handler.
### Reference Example
```typescript
import Animated, {
useAnimatedScrollHandler,
useComposedEventHandler,
} from 'react-native-reanimated';
function ComposedEventHandlerExample() {
const onScrollHandler1 = useAnimatedScrollHandler({
onScroll(e) {
console.log('Scroll handler 1 onScroll event');
},
});
const onScrollHandler2 = useAnimatedScrollHandler({
onScroll(e) {
console.log('Scroll handler 2 onScroll event');
},
});
const composedHandler = useComposedEventHandler([
onScrollHandler1,
onScrollHandler2,
]);
return (
);
}
```
#### Arguments
- **`handlers`**: An array of event handlers created using the `useEvent` hook. The `useComposedEventHandler` hook updates whenever there are changes in these handlers.
#### Returns
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.
### Remarks
- 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.
- It functions effectively when used with multiple `Animated components`, triggering event callbacks for each connected component.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## withDelay
`withDelay` is an animation modifier that allows you to initiate an animation after a specified delay period.
### Reference
```typescript
import { withDelay } from "react-native-reanimated"
function App() {
sv.value = withDelay(500, withTiming(0))
// ...
}
```
#### Arguments
- **`delayMs`**: Specifies the duration (in milliseconds) before the animation begins.
- **`delayedAnimation`**: The animation that will be delayed.
- **`reduceMotion`** *(Optional)*: Determines how the animation responds to the device's reduced motion accessibility setting.
#### Returns
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`.
### Example
*(Example content would go here)*
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
***
## useAnimatedSensor
`useAnimatedSensor` allows you to create animations based on device sensor data. It provides access to:
- **Accelerometer**: Measures device acceleration (excluding gravity) along the x, y, and z axes.
- **Gyroscope**: Captures the rotation rate of the device along the x, y, and z axes.
- **Gravity**: Provides the current gravity vector along the x, y, and z axes.
- **Magnetic Field**: Measures the Earth's magnetic field strength and direction in microtesla (μT).
- **Rotation**: Represents the device orientation using Euler angles and a quaternion.
For comprehensive documentation, refer to the Sensors guide on Android Developers and Device Motion in Apple Developer documentation.
### Reference
```typescript
import { useAnimatedSensor, SensorType } from "react-native-reanimated"
function App() {
const gyroscope = useAnimatedSensor(SensorType.GYROSCOPE)
useDerivedValue(() => {
const { x, y, z } = gyroscope.sensor.value
})
}
```
#### Arguments
##### `sensorType`
Specifies the sensor type using a `SensorType` enum:
- `ACCELEROMETER`: Measures device acceleration in m/s².
- `GYROSCOPE`: Captures rotation rate in radians per second.
- `GRAVITY`: Provides gravity vector in m/s².
- `MAGNETIC_FIELD`: Measures magnetic field strength in microtesla (μT).
- `ROTATION`: Represents orientation using Euler angles and a quaternion.
##### `config` (Optional)
|Name|Type|Default|Description|
|-|-|-|-|
|interval|`number \| "auto"`|`"auto"`|Time between sensor readings in milliseconds. `"auto"` matches the device's screen refresh rate.|
|adjustToInterfaceOrientation|`boolean`|`true`|Adjusts measurements to the current interface orientation.|
|iosReferenceFrame|`IOSReferenceFrame`|`IOSReferenceFrame.Auto`|Frame of reference for iOS sensors.|
Available `IOSReferenceFrame` options:
- `xArbitraryZVertical`: Z axis is vertical, X axis arbitrary in horizontal plane.
- `xArbitraryCorrectedZVertical`: Improved rotation accuracy with Z vertical and X arbitrary.
- `XMagneticNorthZVertical`: Z axis vertical, X points to magnetic north.
- `XTrueNorthZVertical`: Z axis vertical, X points to geographic north.
- `Auto`: Defaults based on device capabilities.
#### Returns
`useAnimatedSensor` returns an object:
|Name|Type|Description|
|-|-|-|
|sensor|`SharedValue`|Shared value with sensor measurements.|
|unregister|`() => void`|Stops listening to sensor updates when called.|
|isAvailable|`boolean`|Indicates if the sensor is available for use.|
|config|`SensorConfig`|Contains sensor configuration details.|
The shared value from the **rotation sensor** includes:
- Euler angles: `roll`, `pitch`, `yaw`.
- Quaternion components: `qw`, `qx`, `qy`, `qz`.
- Interface orientation.
Other sensors return measurements on x, y, z axes and interface orientation.
`InterfaceOrientation` enum values:
- `ROTATION_0`: Default rotation on Android, portrait on iOS.
- `ROTATION_90`: 90 degrees on Android, landscape right on iOS.
- `ROTATION_180`: 180 degrees on Android, upside down on iOS.
- `ROTATION_270`: 270 degrees on Android, landscape left on iOS.
### Example
```typescript
export default function App() {
const gravity = useAnimatedSensor(SensorType.GRAVITY);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{ translateX: withSpring(gravity.sensor.value.x * 20) },
{ translateY: withSpring(gravity.sensor.value.y * 20) },
],
};
});
return (
);
}
```
### Remarks
- On iOS, enable location services (`Settings > Privacy > Location Services`) to read sensor data.
- On Web, ensure the device supports sensors and the application is served over HTTPS.
- Most sensors operate at resolutions up to 100Hz.
- Sensor data can be accessed on both UI and JavaScript threads.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## dispatchCommand
The `dispatchCommand` function enables the execution of commands directly on a native component from the UI thread.
### Reference
```typescript
import { dispatchCommand } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
const gesture = Gesture.Tap().onStart(() => {
dispatchCommand(animatedRef, 'focus');
});
return (
<>
>
);
}
```
#### Arguments
- **`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.
- **`commandName`**: The name of the command to execute, such as `'focus'` or `'scrollToEnd'`.
- **`args` (Optional)**: An array of arguments for the command. Defaults to an empty array if not provided.
### Example
```typescript
const goDown = Gesture.Tap().onStart(() => {
dispatchCommand(tosRef, "scrollToEnd", [true])
dispatchCommand(loginRef, "focus")
})
```
### Remarks
- Commands vary depending on the component. Refer to the relevant React Native documentation for available commands specific to each component.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|❌|
## setNativeProps
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.
> **Caution:**\
> Prefer using `useAnimatedStyle` and `useAnimatedProps` when animating styles or properties, reserving `setNativeProps` for exceptional situations.
### Reference
```typescript
import { setNativeProps } from 'react-native-reanimated';
function App() {
const animatedRef = useAnimatedRef();
const tap = Gesture.Tap().onEnd(() => {
setNativeProps(animatedRef, { text: '' });
});
return ;
}
```
#### Arguments
- **`animatedRef`:**\
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.
- **`updates`:**\
An object containing properties that need updating, which can include both style properties (e.g., `width`, `backgroundColor`) and regular properties (e.g., `text`).
#### Returns
The function returns `undefined`.
### Remarks
- Prioritize using `useAnimatedStyle` and `useAnimatedProps` for animating styles or properties.
- Ensure that `setNativeProps` is used exclusively on the UI thread.
- 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.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
***
## React Native Reanimated: useReducedMotion Hook (Version 3.x)
### Overview
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.
### Reference
```typescript
import { useReducedMotion } from "react-native-reanimated"
function App() {
const reduceMotion = useReducedMotion()
if (reduceMotion) {
// Display static content ✨
} else {
// Run animations ✨
}
// Additional logic...
}
```
#### Returns
The `useReducedMotion` hook returns a boolean value indicating whether the reduced motion setting was enabled at the start of the app.
### Example Usage
```typescript
import { useReducedMotion } from 'react-native-reanimated';
function App() {
const reduceMotion = useReducedMotion();
if (reduceMotion) {
return ;
} else {
return ;
}
}
```
### Remarks
- Changing the reduced motion setting does not trigger a component rerender.
- Unlike `AccessibilityInfo.isReduceMotionEnabled()`, `useReducedMotion` provides the value synchronously.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
This hook is compatible across Android, iOS, and Web platforms.
## makeMutable
**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).
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.
The object produced by `makeMutable` mirrors that returned by the `useSharedValue` hook, ensuring consistent usage thereafter.
### Reference
```typescript
import { makeMutable } from "react-native-reanimated"
const mv = makeMutable(100)
```
#### Arguments
##### `initial`
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.
#### Returns
`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.
### Example
### Remarks
**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.
- All remarks applicable to the `useSharedValue` hook are relevant to `makeMutable`.
- Avoid invoking `makeMutable` directly within component scope. Component re-renders will generate a new object, potentially resetting the initial value and losing previous state.
```typescript
function App() {
const [counter, setCounter] = useState(0)
const mv = makeMutable(counter) // 🚨 creates a new mutable value on each render
useEffect(() => {
const interval = setInterval(() => {
setCounter((prev) => prev + 1) // updates the counter stored in component state
}, 1000)
return () => {
clearInterval(interval)
}
}, [mv])
useAnimatedReaction(
() => mv.value,
(value) => {
console.log(value) // prints 0, 1, 2, ...
}
)
}
```
- 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.
```typescript
function App() {
const mv = useMemo(() => makeMutable(0), [])
useEffect(() => {
mv.value = withRepeat(withSpring(100), -1, true) // creates an infinite animation
return () => {
cancelAnimation(mv) // ✅ stops the infinite animation on component unmount
}
}, [])
}
```
- `cancelAnimation` is not needed for non-animated values as they are automatically garbage collected when no references remain.
```typescript
const someFlag = makeMutable(false)
function App() {
someFlag.value = true // ✅ no need to cancel the animation later on
}
```
- 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).
#### Comparison with `useSharedValue`
|Feature|`makeMutable`|`useSharedValue`|
|-|-|-|
|Object Creation|Creates a new object on each call|Reuses the same object on each call|
|Initial Value Change|A new object is created if `initial` changes|The initially created object remains unchanged if `initialValue` changes|
|Scope Usage|Can be used outside of component scope|Limited to use within component scope|
|Loop Usage|Usable in loops with variable iterations|Usable in loops only if the number of hooks (`useSharedValue` calls) is constant|
|Animation Cancellation|Does not automatically cancel animations on unmount|Automatically cancels animations when the component unmounts|
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Accurate Call Stacks
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.
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.
### Reference
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.
```typescript
// metro.config.js
import { wrapWithReanimatedMetroConfig } from "react-native-reanimated/metro-config"
const config = {
// Your existing Metro configuration options
}
export default wrapWithReanimatedMetroConfig(config)
```
### Example
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.
|Before|After|
|-|-|
|||
### Remarks
- `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**.
|Collapsed|Expanded|
|-|-|
|||
- 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.
## withClamp
`withClamp` is an animation modifier that restricts the movement of your animation within a specified range. It's typically used in conjunction with `withSpring`.
### Reference
```typescript
import { withClamp } from "react-native-reanimated"
function App() {
sv.value = withClamp({ min: -1, max: 1 }, withSpring(0))
// ...
}
```
#### Arguments
##### `config`
An object containing the following properties:
|Name|Type|Description|
|-|-|-|
|min|number|Optional. The lowest value your animation can reach.|
|max|number|Optional. The highest value your animation can reach.|
##### `animation`
The spring animation you wish to clamp.
```typescript
const clampedStyleWithDelay = useAnimatedStyle(() => {
return {
width: withClamp({ min: 0, max: 100 }, withSpring(randomWidth.value)),
}
})
```
#### Returns
`withClamp` returns an animation object. This can be directly assigned to a shared value or used as a style value in `useAnimatedStyle`.
|Platform|Supported|
|-|-|
|Android|✅|
|iOS|✅|
|Web|✅|
## Logger configuration
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.
By default, the logger configuration requires no setup and displays all warnings and errors. To customize this behavior, use the `configureReanimatedLogger` function.
### Reference
To alter the default Reanimated logger settings, import `configureReanimatedLogger` from `react-native-reanimated` and invoke it with your desired configuration:
```typescript
import {
configureReanimatedLogger,
ReanimatedLogLevel,
} from "react-native-reanimated"
// Default configuration example
configureReanimatedLogger({
level: ReanimatedLogLevel.warn,
strict: true, // Strict mode is enabled by default
})
```
#### Configuration Options
- **`level`:** Specifies the minimum log level to display using a value from `ReanimatedLogLevel`.
- **`strict`:** A boolean that toggles strict mode. Enabling it results in additional warnings to help identify potential code issues.
### Remarks
- The logger configuration is global, affecting all Reanimated warnings and errors. It cannot be configured on a per-file or per-component basis.
- Call `configureReanimatedLogger` before creating any Reanimated animations, typically in the root file of your application.
- 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.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## React Native Reanimated: ReducedMotionConfig
**Version:** 3.x
### Overview
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.
> **Caution:** The new configuration will be applied globally across the entire application.
### Reference
```typescript
import { ReducedMotionConfig, ReduceMotion } from 'react-native-reanimated';
function App() {
return (
// ...
// ...
);
}
```
#### Arguments
##### `mode`
This parameter determines how animations should respond to the device's reduced motion accessibility setting:
- **`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.
- **`ReduceMotion.Always`:** Consistently disables animations, regardless of the device's accessibility configuration.
- **`ReduceMotion.Never`:** Ensures that animations remain enabled at all times.
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
- Reference
- Arguments
- Example
- Platform compatibility
## Worklets
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.
### Creating Worklets
To define a custom worklet, use the `'worklet';` directive at the start of your function:
```typescript
function myWorklet() {
"worklet"
console.log("Hello from a worklet")
}
```
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.
### Automatic Workletization
When using Reanimated and Gesture Handler, code is typically automatically workletized and executed on the UI thread:
```typescript
import { useAnimatedStyle } from "react-native-reanimated"
function App() {
const style = useAnimatedStyle(() => {
// Executed on the UI thread
return { opacity: 0.5 }
})
}
```
### Manual Worklet Execution
To manually schedule worklet execution, use `runOnUI`:
```typescript
function myWorklet() {
"worklet"
console.log("Hello from the UI thread")
}
function onPress() {
runOnUI(myWorklet)()
}
```
Arguments can be passed to worklets as follows:
```typescript
function myWorklet(greeting: string) {
"worklet"
console.log(`${greeting} from the UI thread`)
}
function onPress() {
runOnUI(myWorklet)("Howdy")
}
```
### Worklet Closures
Worklets are closures, allowing them to access variables declared outside their scope. Only referenced variables are captured:
```typescript
const width = 135.5
function otherWorklet() {
"worklet"
console.log("Captured width is", width)
}
```
Avoid capturing large objects within worklets to prevent performance issues:
```typescript
const theme = {...}; // Large object
function myWorklet() {
'worklet';
console.log(theme.color); // 🚨 Captures entire `theme` object
}
```
To mitigate this, assign the needed property to a separate variable:
```typescript
const theme = {...};
const color = theme.color;
function myWorklet() {
'worklet';
console.log(color); // ✅ Captures only `color`
}
```
### Returning Data
Worklets can return data within the same thread:
```typescript
function returningWorklet() {
"worklet"
return "I'm back" // On the UI thread
}
function someWorklet() {
"worklet"
const what = returningWorklet() // Still on the UI thread
console.log("On the UI thread, other worklet says", what)
}
```
### Data Sharing Between Threads
Use shared values to pass data between the UI and JS threads:
```typescript
import { useSharedValue } from "react-native-reanimated"
function App() {
const width = useSharedValue(100)
function myWorklet() {
"worklet"
width.value += 50
}
useEffect(() => {
console.log(width.value) // Accessible on both JS and UI threads
}, [])
}
```
### Running Functions on the JS Thread
Use `runOnJS` to execute functions from the UI thread, often for non-worklet functions or React state updates:
```typescript
import { router } from "expo-router"
import { Gesture } from "react-native-gesture-handler"
function App() {
const tap = Gesture.Tap().onEnd(() => {
// Worklet context
runOnJS(router.back)()
})
}
```
Ensure functions passed to `runOnJS` are defined in the JavaScript thread scope:
```typescript
function App() {
const tap = Gesture.Tap().onEnd(() => {
// myFunction is defined on the UI thread 🚨
const myFunction = () => {}
runOnJS(myFunction)() // 💥 Error
})
}
```
### Custom Worklet Runtimes
Worklets can operate in custom runtimes beyond Reanimated's default. Libraries like VisionCamera and LiveMarkdown create their own worklet environments.
Create your own worklet runtime using `createWorkletRuntime`.
## Accessibility
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.
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:
- `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.
- `ReduceMotion.Always`: Consistently disables the animation, regardless of the device's accessibility configuration.
- `ReduceMotion.Never`: Ensures that the animation remains enabled at all times.
By default, all animations are configured with `ReduceMotion.System`.
### Reduced Motion in Animations
```typescript
import { withDelay, withTiming } from "react-native-reanimated"
function App() {
sv1.value = withTiming(0, { reduceMotion: ReduceMotion.System })
sv2.value = withDelay(
1000,
withTiming(toValue, { duration }),
ReduceMotion.System
)
// ...
}
```
When reduced motion is enabled:
- `withSpring` and `withTiming` return the `toValue` immediately.
- `withDecay` returns the current value immediately, considering the clamp parameter.
- `withDelay` initiates the next animation immediately.
- `withRepeat`:
- If `numberOfReps` is infinite or even and the animation is reversed, then the repeated animation does not start.
- Otherwise, the repeated animation runs once.
- `withSequence` exclusively starts animations that have reduced motion disabled.
Higher-order animations pass the configuration to their children only if the children haven't been configured by the user. For example:
This animation will instantaneously reach the `toValue`:
```typescript
import { withDelay, withTiming } from "react-native-reanimated"
function App() {
sv.value = withDelay(
1000,
withTiming(toValue, { duration }),
ReduceMotion.Always
)
// ...
}
```
This animation will execute as usual even if reduced motion is enabled on the device:
```typescript
import { withDelay, withTiming } from "react-native-reanimated"
function App() {
sv.value = withDelay(
1000,
withTiming(toValue, { duration }),
ReduceMotion.Never
)
// ...
}
```
And here `withTiming` will be executed as usual and without delay:
```typescript
import { withDelay, withTiming } from "react-native-reanimated"
function App() {
sv.value = withDelay(
1000,
withTiming(toValue, { duration, reduceMotion: ReduceMotion.Never }),
ReduceMotion.Always
)
// ...
}
```
### Reduced Motion in Layout Animations
```typescript
import { BounceIn } from "react-native-reanimated"
function App() {
const entering = BounceIn.reduceMotion(ReduceMotion.System)
// ...
}
```
When reduced motion is enabled:
- Entering, keyframe, and layout animations instantaneously reach their endpoints.
- Exiting animations and shared transitions are omitted.
### `useReducedMotion`
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.
```typescript
import { BounceIn } from "react-native-reanimated"
function App() {
const reduceMotion = useReducedMotion()
const entering = reduceMotion
? FadeIn.reduceMotion(ReduceMotion.Never)
: BounceIn
// ...
}
```
## Glossary of terms
### Animated Component
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`.
```typescript
import Animated from 'react-native-reanimated';
function App() {
return (
);
}
```
For components not included in Reanimated, you can make their props and styles animatable by wrapping them with `createAnimatedComponent`:
```typescript
import Animated from "react-native-reanimated"
import { Circle } from "react-native-svg"
const AnimatedCircle = Animated.createAnimatedComponent(Circle)
```
### Shared Value
Shared values are essential for animations in Reanimated. They are defined using the `useSharedValue` hook and accessed or modified via their `.value` property.
```typescript
import { useSharedValue } from "react-native-reanimated"
function App() {
const sv = useSharedValue(0)
const handlePress = () => {
sv.value += 10
}
// rest of your glamorous code ✨
}
```
Shared values can store any type and automatically synchronize data between the JavaScript thread and the UI thread.
### Animatable Value
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.
### Animation Function
Animation functions define how animations should behave. Reanimated provides three built-in animation functions:
- `withSpring`: Creates spring-based animations.
- `withTiming`: Creates duration and easing-based animations.
- `withDecay`: Mimics motion with a given deceleration rate.
These can be combined with modifiers for complex animations.
### Animation Modifier
Animation modifiers customize animations. Known as higher-order animations, Reanimated includes:
- `withDelay`: Adds a delay before the animation starts.
- `withRepeat`: Repeats an animation a specified number of times.
- `withSequence`: Chains animations sequentially.
- `withClamp`: Limits animation boundaries to a specific range.
### Animation Object
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.
When passed to a shared value, it is treated as an animatable value:
```typescript
sv.value = withSpring(100)
```
### Animations in Inline Styling
Shared values can be directly used in the `style` property without `useAnimatedStyle`.
Example:
```typescript
function App() {
const width = useSharedValue(100);
return ;
}
```
### Layout Animation Modifier
Layout animation modifiers customize layout animations. Example usage:
```typescript
```
Built-in modifiers include:
- `.duration(durationMs: number)`: Sets the animation length in milliseconds.
- `.easing(easingFunction: EasingFunction)`: Defines the animation curve.
- `.springify()`: Enables spring-based animations.
- `.damping(value: number)`: Controls how quickly a spring stops moving.
- `.withCallback(callback: (finished: boolean) => void)`: Triggers after the animation ends.
### Worklet
Worklets are short-running JavaScript functions executed on the UI thread. They can also run on the JavaScript thread like regular functions.
Code is often automatically workletized and runs on the UI thread by default:
```typescript
const style = useAnimatedStyle(() => {
console.log("Running on the UI thread")
return { opacity: 0.5 }
})
```
Custom worklets can be created using the `"worklet";` directive:
```typescript
function myWorklet() {
"worklet"
console.log("Running on the UI thread")
}
```
Use `runOnUI` to manually execute worklets on the UI thread:
```typescript
function myWorklet(greeting) {
"worklet"
console.log(`${greeting} from the UI thread`)
}
function onPress() {
runOnUI(myWorklet)("Howdy")
}
```
### To Workletize
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.
### JavaScript Thread
The JavaScript thread handles code execution in the app, serving as the primary location for React Native app code execution.
### UI Thread
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.
### Reanimated Babel Plugin
This plugin automatically workletizes certain functions used with Reanimated, reducing boilerplate code. Details are available in the Reanimated Babel plugin README.
## Entering/Exiting animations
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:
#### Overview
- **Library**: `react-native-reanimated`
- **Purpose**: To create smooth, performant animations on Android, iOS, and Web platforms.
- **Animations Covered**:
- Pinch
- Pinch Zoom
- Pinch Rotate
- Pinch Scale
- Pinch Translate
- Pinch X
- Pinch Y
- PinchXY
- PinchZoomRotate
- PinchZoomScale
- PinchZoomTranslate
- PinchZoomX
- PinchZoomY
- PinchZoomXY
- PinchZoomRotateScale
- PinchZoomRotateTranslate
- PinchZoomRotateX
- PinchZoomRotateY
- PinchZoomRotateXY
- PinchZoomScaleTranslate
- PinchZoomScaleX
- PinchZoomScaleY
- PinchZoomScaleXY
- PinchZoomTranslateX
- PinchZoomTranslateY
- PinchZoomTranslateXY
- PinchZoomRotateScaleTranslate
- PinchZoomRotateScaleX
- PinchZoomRotateScaleY
- PinchZoomRotateScaleXY
- PinchZoomRotateTranslateX
- PinchZoomRotateTranslateY
- PinchZoomRotateTranslateXY
- PinchZoomScaleTranslateX
- PinchZoomScaleTranslateY
- PinchZoomScaleTranslateXY
- PinchZoomRotateScaleTranslateX
- PinchZoomRotateScaleTranslateY
- PinchZoomRotateScaleTranslateXY
- Other animations like Bounce, Fade, Flip, etc.
#### Animation Configuration
##### Time-based Modifiers
- **Function**: `withTiming`
- **Customization**:
- `.easing(easingFunction: EasingFunction)`: Defines the animation curve. Default is `Easing.inOut(Easing.quad)`.
- Note: These modifiers do not affect spring animations.
##### Spring-based Modifiers
- **Function**: `withSpring`
- **Customization**:
- `.springify()`: Enables spring-based configuration.
- `.damping(value: number)`: Controls how quickly the spring stops. Default is `10`.
- `.mass(value: number)`: Represents the weight of the spring. Lower values make animations faster. Default is `1`.
- `.stiffness(value: number)`: Determines bounciness. Default is `100`.
- `.overshootClamping(value: boolean)`: Prevents bouncing over the target position. Default is `false`.
- `.restDisplacementThreshold(value: number)`: Displacement threshold for snapping to the final position without oscillations. Default is `0.001`.
- `.restSpeedThreshold(value: number)`: Speed threshold for snapping to the final position without oscillations. Default is `2`.
##### Common Modifiers
- **Customization**:
- `.duration(durationMs: number)`: Length of the animation in milliseconds. Default is `300`.
- `.delay(durationMs: number)`: Delay before starting the animation. Default is `0`.
- `.randomDelay()`: Randomizes delay between `0` and provided value, defaulting to `1000ms` if not specified.
- `.reduceMotion(reduceMotion: ReduceMotion)`: Adjusts animation based on device's reduced motion settings.
- `.withInitialValues(values: StyleProps)`: Overrides initial configuration of the animation.
- `.withCallback(callback: (finished: boolean) => void)`: Executes a callback after the animation ends, indicating if it finished without interruptions.
#### Platform Compatibility
- **Android**: Supported
- **iOS**: Supported
- **Web**: Supported
This guide provides developers with the tools to create and customize animations effectively across multiple platforms using `react-native-reanimated`.
## Troubleshooting React Native Reanimated Build Issues on Windows
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:
- `Execution failed for task ':react-native-reanimated:buildCMakeDebug[x86_64]'`
- `Execution failed for task ':react-native-reanimated:buildCMakeRelWithDebInfo[arm64-v8a]'`
- `Task :react-native-reanimated:buildCMakeDebug[x86_64] FAILED`
- `C/C++: ninja: error: mkdir(...): No such file or directory`
- `C++ build system [build] failed while executing`
- `Picked up _JAVA_OPTIONS`
### What Not to Do
If you encounter any of the above errors, avoid these actions:
#### ❌ Avoid Disabling New Architecture
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.
#### ❌ Avoid Downgrading Android Gradle Plugin (AGP)
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.
#### ❌ Avoid Downgrading Reanimated or Other Dependencies
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.
#### ❌ Avoid Posting Duplicate "Same Issue" Comments
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.
### Recommended Actions
#### ✅ Ensure Correct Environment Setup
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.
#### ✅ Use Compatible Reanimated Version
Use the latest supported version of Reanimated based on your app setup:
- **Expo SDK**: Match major and minor versions with Expo SDK.
- Example: Expo SDK 52 supports `~3.16.x`. Update to the latest patch, e.g., `3.16.7`.
|Expo SDK Version|Reanimated Version|
|-|-|
|`52`|`~3.16.1`|
|`51`|`~3.10.1`|
|`50`|`~3.6.2`|
- **Expo Prebuild or React Native without Framework**: Use a version compatible with your React Native version according to the Compatibility table.
#### ✅ Use Appropriate CMake Version
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`.
#### ✅ Use Appropriate Ninja Version
Use Ninja `1.12.0` or newer (latest is `1.12.1`) as older versions may not handle long paths correctly.
#### ✅ Use Compatible Android NDK Version
Match the NDK version with that used in the official app template. It should be installed automatically during app build.
#### ✅ Unset `_JAVA_OPTIONS`
Unsetting this environment variable can resolve certain errors and allow builds to pass.
#### ✅ Enable Long Paths Support in Windows Registry
Follow instructions to enable long paths support on Windows.
#### ✅ Avoid Whitespace in Project Path
Paths with spaces may cause issues. Move projects to directories without whitespace, e.g., `D:\Mobile Apps\MyAwesomeProject`.
#### ✅ Ensure Short Project Path
Avoid paths longer than 240 characters. Move or clone the project to a shorter path, e.g., `D:\AwesomeProject`.
#### ✅ Remove or Invalidate Caches
Clear compilation artifacts in directories like:
- `android\build`
- `android\.cxx`
- `android\.gradle`
- `node_modules\react-native-reanimated\android\build`
Invalidate Android Studio caches (File → Invalidate Caches…).
#### ⚠️ Persistent Issues
If problems persist after following these steps, submit an issue in the repository with full build logs and a minimal reproducible example.
## Compatibility Table
### Currently Supported React Native Versions (Paper)
|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|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
|3.6.x – 3.8.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|
|3.5.x|no|no|no|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
|3.3.x – 3.4.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|
|3.0.x – 3.2.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
|2.14.x – 2.17.x|yes|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|
|2.11.x – 2.13.x|yes|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|
|2.10.x|yes|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|
|2.5.x – 2.9.x|yes|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|
|2.3.x – 2.4.x|yes|yes|yes|yes|yes|no|no|no|no|no|no|no|no|no|no|no|no|no|
**Note:** Reanimated 2 will not receive support for the newest React Native versions. To access the latest features and updates, upgrade to Reanimated 3.
### Supported React Native Versions on the New Architecture (Fabric)
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.
Reanimated supports bridgeless mode.
|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|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|3.18.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|yes|
|3.17.4 - 3.17.5|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|yes|no|
|3.17.1 – 3.17.3|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|
|3.17.0|no|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|
|3.16.7|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|yes|no|no|no|
|3.16.0 – 3.16.6|no|no|no|no|no|no|no|no|no|no|no|yes|yes|yes|no|no|no|no|
|3.15.x|no|no|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|
|3.9.x – 3.14.x|no|no|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|
|3.6.x – 3.8.x|no|no|no|no|no|no|no|no|no|yes|yes|no|no|no|no|no|no|no|
|3.1.x – 3.5.x|no|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|
|3.0.x|no|no|no|no|no|no|no|no|yes|no|no|no|no|no|no|no|no|no|
## useSharedValue
`useSharedValue` is a hook that allows you to define shared values within your components.
### Reference
```typescript
import { useSharedValue } from "react-native-reanimated"
function App() {
const sv = useSharedValue(100)
// Accessing the shared value
console.log(sv.value)
// Modifying the shared value
sv.value += 50
}
```
#### Arguments
##### `initialValue`
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`.
#### Returns
`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.
##### React Compiler Support
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.
```typescript
function App() {
const sv = useSharedValue(100)
const animatedStyle = useAnimatedStyle(() => {
"worklet"
return { width: sv.get() * 100 }
})
const handlePress = () => {
sv.set((value) => value + 1)
}
}
```
### Remarks
- 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.
- 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.
- 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.
- 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.
```typescript
function App() {
const sv = useSharedValue(100) // initially set to 100
sv.value += 50 // modifying the shared value
console.log(sv.value) // logs 100 due to asynchronous update on JS thread
}
```
- Avoid destructuring assignment with shared values. While valid in JavaScript, it prevents Reanimated from maintaining reactivity.
```typescript
function App() {
let { value } = sv // avoid this pattern
console.log(value) // reading is fine
value += 50 // does not update styles
}
```
- When storing objects in a shared value, ensure to reassign the entire object rather than modifying its properties individually.
```typescript
function App() {
const sv = useSharedValue({ x: 0, y: 0 })
sv.value.x = 50 // loses reactivity
sv.value = { x: 50, y: 0 } // correct approach
}
```
- For large arrays or complex objects in a shared value, use the `.modify` method to alter the existing value without creating a new one.
```typescript
function App() {
const sv = useSharedValue([1, 2, 3])
sv.value.push(1000) // loses reactivity
sv.value = [...sv.value, 1000] // creates a new copy
sv.modify((value) => {
"worklet"
value.push(1000) // correct approach
return value
})
}
```
### Platform Compatibility
|Android|iOS|Web|
|-|-|-|
|✅|✅|✅|
## Contributing
Thank you for considering contributing to Reanimated. Contributions can range from triaging issues and enhancing documentation to reviewing Pull Requests and submitting code changes.
### Ways to Contribute
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.
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.
1. **Reviewing Pull Requests**: Review submitted Pull Requests to identify potential issues or bugs that may have been overlooked, ensuring high-quality contributions.
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.
#### Repository Structure
The Reanimated repository is organized as follows:
```
├── apps
│ ├── common-app // Shared source for example apps
│ ├── paper-example // React Native app using Old Architecture
│ ├── fabric-example // React Native app using New Architecture
│ ├── macos-example // React Native for MacOS wrapper
│ ├── next-example // Next.js wrapper
│ ├── tvos-example // React Native for TVOS wrapper
│ └── web-example // React Native for Web wrapper
└── packages
├── docs-reanimated // Documentation source
├── eslint-plugin-reanimated // ESLint plugin source
└── react-native-reanimated
├── android // Android native code
├── apple // iOS native code
├── Common // Shared C++ code
├── scripts // CI pipeline scripts
├── src // Reanimated JS source
└── plugin // Babel plugin source
```
### Handling Open Issues
Providing detailed descriptions and reproducible examples for issues can significantly aid other contributors. Ensure that issues include:
- A cloneable repository.
- Clear reproduction steps.
- Comprehensive descriptions.
- Relevant stack traces.
If these details are missing, consider asking the issue owner or providing them yourself to facilitate quicker resolutions.
### Documentation Assistance
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:
1. Clone `react-native-reanimated`.
1. Navigate to `packages/docs-reanimated`.
1. Run `yarn && yarn start` to preview changes locally.
#### Documentation Structure
Maintain a consistent structure for clarity and ease of navigation:
1. **Introduction**: Briefly describe the feature.
1. **Reference**: Provide simple usage examples with type definitions.
1. **Arguments**: Detail accepted arguments.
1. **Returns**: Explain returned values.
1. **Example**: Include videos, GIFs, or interactive demos in both light and dark modes.
1. **Remarks**: Highlight non-obvious details like platform-specific quirks.
1. **Platform Compatibility**: Specify supported platforms.
#### Writing Style Guide
- Use active voice for clarity (e.g., "The function receives the arguments").
- Write short, clear sentences to aid comprehension.
- Organize information into lists for better readability.
- Avoid acronyms unless globally recognized (e.g., UI, API).
- Use contractions for a conversational tone.
#### Embedding Interactive Examples
Use the `InteractiveExample` component with `src` and `component` props to create engaging examples. For videos:
```typescript
import AnimatedKeyboardSrc from '!!raw-loader!@site/src/examples/AnimatedKeyboard';
}
/>;
```
For interactive components:
```typescript
import DecayTrain from '@site/src/examples/DecayTrain';
import DecayTrainSrc from '!!raw-loader!@site/src/examples/DecayTrain';
}
label="Grab and drag the train"
/>;
```
### Contributing Code
Submit Pull Requests to address issues or introduce new features. Start with "good first issue" tasks if you're new to open-source contributions.
#### Working with Android
1. Install dependencies: `yarn && yarn build`.
1. Navigate to `apps/paper-example` and run `yarn start`.
1. Open the project in Android Studio at `react-native-reanimated/apps/paper-example/android`.
#### Working with iOS
1. Install dependencies: `yarn && yarn build`.
1. Run `cd apps/paper-example/ios && bundle install && bundle exec pod install`.
1. Start Metro bundler: `cd apps/paper-example && yarn start`.
1. Open the project in Xcode at `react-native-reanimated/apps/paper-example/ios/ReanimatedExample.xcworkspace`.
#### Preparing a Pull Request
When ready, open a Pull Request using the provided template:
1. **Summary**: Link relevant issues and describe your changes.
1. **Test Plan**: Provide instructions for testing, including code from `EmptyExample` if applicable.
#### Testing Changes Locally
To test changes in your project, create a patch with `git diff` or point to a specific commit in `package.json`.
Thank you for contributing! 🎉
## Debugging worklets
### Overview
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.
#### React Native Debugging Tools
The following tools have been evaluated for compatibility with React Native apps using the Reanimated library:
- **Chrome Debugger (React Native Debugger):** Utilizes a web worker in your browser to execute app JavaScript code, supporting all available runtimes in React Native.
- **Chrome DevTools:** Connects to a remote JavaScript runtime, allowing code execution on the device. Note: Not compatible with JSC.
- **Flipper (Hermes debugger):** Facilitates using Chrome DevTools and offers additional UI inspection tools.
- **Safari DevTools:** Available only for iOS devices running JSC, similar in functionality to Chrome DevTools by connecting to a remote runtime.
- **React Developer Tools:** A standalone app for debugging UI through an inspector, monitoring performance, and profiling the application.
#### JS Context vs. UI Context
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.
#### Debugging Web Apps
For web applications, standard browser tools or any preferred debugging tools can be used without issues when employing Reanimated on the web.
### Compatibility Summary
|Tool|Platform|JSC|Hermes|V8|
|-|-|-|-|-|
|Chrome Debugger|Android|⚛️ ✅¹|⚛️ ✅¹|⚛️ ✅¹|
||iOS|⚛️ ✅¹|⚛️ ✅¹|N/A|
|Chrome DevTools|Android|N/A|⚛️ ✅²|⚛️|
||iOS|N/A|⚛️ ✅²|N/A|
|Flipper (Hermes debugger)|Android|N/A|⚛️ ✅²|⚛️|
||iOS|N/A|⚛️ ✅²|N/A|
|Safari DevTools|Android|N/A|N/A|N/A|
||iOS|⚛️ ✅|N/A|N/A|
|React Developer Tools|Android|⚛️|⚛️|⚛️|
||iOS|⚛️|⚛️|N/A|
¹ - Functions use web implementations, running worklets on the JS thread. Measure and Layout Animations are unavailable. ² - Experimental feature.
#### Legend
- ⚛️ ✅: Special features for React Native apps using Reanimated
- ⚛️: Standard functionality with no worklet debugging available
- N/A: Not applicable in React Native apps
**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.
### Tool-Specific Details
#### Chrome Debugger
|Platform|JSC|Hermes|V8|
|-|-|-|-|
|Android|⚛️ ✅|⚛️ ✅|⚛️ ✅|
|iOS|⚛️ ✅|⚛️ ✅|N/A|
**Summary:** Functions use web implementations, running on the JS thread. Measure and Layout Animations are unavailable.
#### Chrome DevTools
|Platform|JSC|Hermes|V8|
|-|-|-|-|
|Android|N/A|⚛️ ✅²|⚛️|
|iOS|N/A|⚛️ ✅²|N/A|
**Summary:** Both contexts can be debugged. This is an experimental feature.
#### Flipper (Hermes Debugger)
|Platform|JSC|Hermes|V8|
|-|-|-|-|
|Android|N/A|⚛️ ✅²|⚛️|
|iOS|N/A|⚛️ ✅²|N/A|
**Summary:** Both contexts can be debugged. This is an experimental feature.
#### Safari DevTools
|Platform|JSC|Hermes|V8|
|-|-|-|-|
|Android|N/A|N/A|N/A|
|iOS|⚛️ ✅|N/A|N/A|
**Summary:** Available only on iOS devices with the JSC engine. Worklet debugging is supported.
#### React Developer Tools
|Platform|JSC|Hermes|V8|
|-|-|-|-|
|Android|⚛️|⚛️|⚛️|
|iOS|⚛️|⚛️|N/A|
**Summary:** Functions as expected, with profiler and layout inspector available.
#### Additional Notes
- **Console Logs:** Always appear in the primary JS runtime.
- **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.
*Efforts are ongoing to enhance debugging experiences with Chrome DevTools and Flipper on Hermes.*