安装 Reanimated 与共享值
安装 react-native-reanimated,添加 Babel 插件,使用 useSharedValue 创建共享值,并通过 useAnimatedStyle 将其连接到动画样式。
安装 Reanimated 与共享值 是 CoddyKit 上的免费 React Native Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Native Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Native Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Reanimated Exists
React Native Reanimated is a more powerful animation library that goes beyond what the built-in Animated API can achieve. While the Animated API moves animation config to native once and runs it there, Reanimated lets you run arbitrary JavaScript-like logic — called worklets — directly on the UI thread, frame by frame.
This enables gesture-driven animations where the animation responds in real time to finger position, impossible with the Animated API's pre-configured approach. Reanimated 3 is the current version and is the foundation of React Native Gesture Handler's smooth interactions.
Installing react-native-reanimated
Install Reanimated from npm, then add the Babel plugin to babel.config.js. The Babel plugin transforms worklet functions at build time so they can run on the UI thread. Without the plugin the library will silently fail at runtime.
For Expo managed workflow, the library must be compatible with your SDK version. Check the Reanimated compatibility table before installing. After installation you must rebuild the native app — Reanimated cannot be added via OTA update.
// Terminal:
// npx expo install react-native-reanimated
// babel.config.js:
module.exports = {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'],
};
// IMPORTANT: Reanimated plugin must be listed LASTuseSharedValue: The Reanimated Primitive
useSharedValue is Reanimated's equivalent of Animated.Value. It creates a value that is shared between the JavaScript thread and the UI thread, and can be read and written from worklets running on the UI thread without crossing the bridge.
Unlike useState, writing to a shared value does NOT trigger a React re-render. Instead, it directly updates the animated style on the UI thread. This is what enables smooth gesture tracking — updating position 60+ times per second without React involvement.
import { useSharedValue } from 'react-native-reanimated';
import { useEffect } from 'react';
export default function MyComponent() {
const offset = useSharedValue(0);
const opacity = useSharedValue(1);
// Read the value: offset.value
// Write to it: offset.value = 100
}useAnimatedStyle: Connecting Values to Styles
useAnimatedStyle creates a style object that is recalculated on the UI thread whenever any shared value it reads changes. You pass a worklet function that returns a style object, reading shared values with .value. Connect the returned style to a ReanimatedView (imported as Animated.View from Reanimated).
This is the bridge between shared values and the visible UI. The style function runs on the UI thread, so it has zero impact on React rendering or the JavaScript thread.
import Animated, { useSharedValue, useAnimatedStyle } from 'react-native-reanimated';
export default function Box() {
const offset = useSharedValue(0);
const animatedStyles = useAnimatedStyle(() => ({
transform: [{ translateX: offset.value }],
}));
return <Animated.View style={[styles.box, animatedStyles]} />;
}withTiming and withSpring Animations
Instead of calling Animated.timing on a shared value, you assign it the return value of withTiming or withSpring. These are animation functions that drive the shared value toward a target value over time, evaluated on the UI thread.
Assigning offset.value = withTiming(100) starts a smooth timing animation. Assigning offset.value = withSpring(100) starts a spring. This assignment syntax is simpler than the Animated API's imperative .start() pattern.
import { useSharedValue, withTiming, withSpring } from 'react-native-reanimated';
const offset = useSharedValue(0);
// Trigger a timing animation:
function moveRight() {
offset.value = withTiming(200, { duration: 500 });
}
// Trigger a spring:
function springRight() {
offset.value = withSpring(200, { damping: 15, stiffness: 100 });
}Animating Opacity and Scale
Opacity and scale shared values work exactly the same way — create a shared value, build an animated style with useAnimatedStyle, and assign animation functions to the value to trigger transitions. Multiple shared values can be combined in a single useAnimatedStyle.
The key advantage over the Animated API is that the worklet function in useAnimatedStyle runs inline with gesture events on the UI thread, enabling perfectly smooth real-time tracking.
const scale = useSharedValue(1);
const opacity = useSharedValue(0);
const style = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ scale: scale.value }],
}));
// Animate on press:
function press() {
scale.value = withSpring(0.9);
opacity.value = withTiming(0.7, { duration: 150 });
}
function release() {
scale.value = withSpring(1);
opacity.value = withTiming(1, { duration: 150 });
}useAnimatedStyle Worklet Rules
The function passed to useAnimatedStyle is a worklet — it runs on the UI thread, not the JavaScript thread. This means it cannot access JavaScript closures, imported modules, or React state directly. It can only access shared values and primitive constants captured at definition time.
Reanimated's Babel plugin transforms the worklet function to make it UI-thread safe. If you violate these rules, you will see cryptic runtime errors. When in doubt, test with a simple transformation before adding complexity.
const offset = useSharedValue(0);
const MULTIPLIER = 2; // primitives captured OK
// CORRECT: only reads sharedValue and primitive
const style = useAnimatedStyle(() => ({
transform: [{ translateX: offset.value * MULTIPLIER }],
}));
// WRONG: accessing React state would throw
// const [reactState] = useState(0);
// const badStyle = useAnimatedStyle(() => ({
// opacity: reactState, // cannot read React state in worklet
// }));Running Reanimated with Expo Go
Reanimated requires the native module to be compiled into the app binary. In Expo managed workflow, this means you need a development build (created with npx expo run:android or npx expo run:ios) rather than the standard Expo Go app, which does not include Reanimated's native module.
An easy alternative is using Expo's development client (expo-dev-client), which is a customizable Expo Go that includes your own native modules. Install it, rebuild, and scan the QR code to get a development environment that supports Reanimated.
// Install expo-dev-client for Reanimated support:
// npx expo install expo-dev-client
// npx expo run:ios (or run:android)
// Then in babel.config.js ensure:
module.exports = {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'], // must be last
};Chaining Animations with withSequence
Reanimated provides withSequence and withRepeat to compose animations directly in the value assignment, without the separate Animated.sequence or Animated.loop objects. The syntax is more concise and functional.
withRepeat accepts an animation, a repeat count (−1 for infinite), and a boolean to reverse direction. withSequence chains multiple animation phases in order.
import { withTiming, withSpring, withSequence, withRepeat } from 'react-native-reanimated';
// Shake animation: left, right, center
offset.value = withSequence(
withTiming(-10, { duration: 100 }),
withTiming(10, { duration: 100 }),
withTiming(0, { duration: 100 })
);
// Pulse animation (infinite):
opacity.value = withRepeat(
withTiming(0.3, { duration: 600 }),
-1, // repeat forever
true // reverse each cycle
);Reading Shared Values vs React State
An important mental model: shared values are not React state. Writing to offset.value does not cause a re-render. The UI updates via animated styles directly. If you need to synchronize a shared value with React state (e.g., to render conditional JSX), use useAnimatedReaction or runOnJS to call a React state setter from the UI thread.
Understanding this boundary — Reanimated lives outside React's render cycle — is the key to using it effectively without introducing bugs.
import { useAnimatedReaction, runOnJS } from 'react-native-reanimated';
const [isVisible, setIsVisible] = React.useState(true);
const opacity = useSharedValue(1);
// React to shared value changes on JS thread:
useAnimatedReaction(
() => opacity.value,
(current) => {
if (current === 0) runOnJS(setIsVisible)(false);
}
);Reanimated vs Animated API Summary
When to use each animation system:
- Animated API — Simple entrance/exit animations, opacity fades, pre-configured sequences. Lower learning curve, ships with React Native, sufficient for most apps.
- Reanimated — Gesture-responsive animations, real-time tracking, complex interactive physics. Required when animation must respond to live gesture position frame by frame.
Many production apps use Animated API for simple UI transitions and Reanimated only for gesture-driven components like swipeable cards, bottom sheets, and drag-and-drop.
Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: useSharedValue creates a value shared between the JS and UI threads for zero-bridge-overhead animations, useAnimatedStyle connects shared values to component styles via a UI-thread worklet, and withTiming and withSpring are assigned to sharedValue.value to start animations. Next up we explore worklets and how they enable complex gesture logic running entirely on the UI thread.
常见问题解答
「安装 Reanimated 与共享值」课时是免费的吗?
是的 — 「安装 Reanimated 与共享值」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Native Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Native Academy 课程共包含 4 节课。
「安装 Reanimated 与共享值」这节课中我会学到什么?
安装 react-native-reanimated,添加 Babel 插件,使用 useSharedValue 创建共享值,并通过 useAnimatedStyle 将其连接到动画样式。 你通过在浏览器中直接运行的动手代码来练习 React Native Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Native Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Native Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「安装 Reanimated 与共享值」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Native Academy 课中编写并运行代码吗?
能。每节 React Native Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 安装 Reanimated 与共享值
- Worklet 与在 UI 线程上运行代码
- 使用 Gesture Handler 实现平移与滑动手势
- 捏合缩放与旋转