React Native Redash
Redash is a utility library specifically designed to augment React Native Reanimated and React Native Gesture Handler, providing a collection of powerful helper functions and components for building complex, performant animations and interactions in React Native applications. It serves as a comprehensive toolbelt, simplifying common animation patterns that are frequently showcased in the popular 'Can it be done in React Native?' YouTube series. The current stable version is 18.1.5, with a consistent release cadence focusing on bug fixes and compatibility updates for new Reanimated versions. It maintains strong ties to the Reanimated ecosystem, abstracting away complex mathematical operations and animation logic into more accessible APIs, differentiating itself by its curated set of practical utilities for advanced animation scenarios.
Common errors
-
Error: Reanimated 1 is no longer supported.
cause Attempting to use `react-native-redash` v17 or higher with `react-native-reanimated` v1.fixUpgrade `react-native-reanimated` to version 2.0.0 or higher, or downgrade `react-native-redash` to `v14.2.2` if `react-native-reanimated` v1 is a strict requirement. -
TypeError: undefined is not a function (evaluating 'mix(...)')
cause The `mix` function (or other Redash utilities) was not correctly imported or `react-native-redash` is not properly linked/installed.fixVerify that `import { mix } from 'react-native-redash';` is correct. Ensure `react-native-redash` is installed and that your native module linking (if applicable) is complete. Clean your build cache and rebuild the app. -
Invariant Violation: `new NativeEventEmitter()` was called with a non-null argument without the corresponding native module being installed.
cause This error typically indicates that the native modules for `react-native-gesture-handler` or `react-native-reanimated` are not correctly linked or initialized, especially after a fresh install or adding new packages.fixRun `npx pod-install` in your `ios/` directory (for iOS), clear the Metro bundler cache (`npm start -- --reset-cache` or `yarn start --reset-cache`), and then rebuild your application (`npx react-native run-ios` or `npx react-native run-android`). -
Tried to synchronously call an asynchronously-available module. You need to ensure the module is importing 'react-native-reanimated' first.
cause This is a common setup issue with `react-native-reanimated`, indicating that its Babel plugin might not be correctly configured or the cache is stale.fixEnsure that `plugins: ['react-native-reanimated/plugin']` is present and correctly ordered as the last plugin in your `babel.config.js` file. Then, clear your Metro bundler cache and rebuild the application.
Warnings
- breaking Redash v17.0.0 introduced a breaking change, dropping support for React Native Reanimated v1. Applications using Reanimated v1 must remain on Redash v14.2.2 or upgrade their Reanimated dependency.
- breaking Redash v18.0.0 changed the internal format of its matrix math utilities. Any code directly manipulating or relying on the previous matrix representation will break.
- gotcha Redash relies heavily on its peer dependencies `react-native-reanimated` and `react-native-gesture-handler`. Version incompatibilities between these libraries can lead to runtime errors or unexpected behavior.
- gotcha Native modules for `react-native-reanimated` and `react-native-gesture-handler` must be correctly linked and configured. Simply installing the npm package is often not enough.
Install
-
npm install react-native-redash -
yarn add react-native-redash -
pnpm add react-native-redash
Imports
- mix
import mix from 'react-native-redash';
import { mix } from 'react-native-redash'; - useVector
const useVector = require('react-native-redash').useVector;import { useVector } from 'react-native-redash'; - ReText
import ReText from 'react-native-redash/ReText';
import { ReText } from 'react-native-redash';
Quickstart
import React from 'react';
import { StyleSheet, View } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
import { mix, useVector } from 'react-native-redash';
import { GestureHandlerRootView, Gesture } from 'react-native-gesture-handler';
export default function App() {
const isPressed = useSharedValue(false);
const offset = useVector(0, 0); // Redash helper for 2D vectors
const animatedStyles = useAnimatedStyle(() => {
const scale = mix(isPressed.value, 1, 1.2); // Redash mix helper
const borderRadius = mix(isPressed.value, 0, 15);
return {
transform: [
{ translateX: offset.x.value },
{ translateY: offset.y.value },
{ scale },
],
borderRadius,
backgroundColor: isPressed.value ? 'dodgerblue' : 'hotpink',
};
});
const panGesture = Gesture.Pan()
.onBegin(() => {
isPressed.value = true;
})
.onChange((event) => {
offset.x.value = event.translationX;
offset.y.value = event.translationY;
})
.onEnd(() => {
isPressed.value = false;
offset.x.value = withSpring(0); // Animate back to origin
offset.y.value = withSpring(0); // Animate back to origin
});
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={styles.container}>
<GestureDetector gesture={panGesture}>
<Animated.View style={[styles.box, animatedStyles]} />
</GestureDetector>
</View>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
box: {
width: 100,
height: 100,
},
});