0Pricing
React Native Academy · Aula

Instalando Reanimated e valores compartilhados

Instale react-native-reanimated, adicione o plugin do Babel, crie valores compartilhados com useSharedValue e conecte-os a estilos animados usando useAnimatedStyle.

Instalando Reanimated e valores compartilhados é uma aula grátis de React Native Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Native Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Native Academy inclui 4 aulas no total.

Partes desta aula ainda não foram traduzidas e aparecem em inglês.

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 LAST

useSharedValue: 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.

Perguntas Frequentes

A aula “Instalando Reanimated e valores compartilhados” é grátis?

Sim — o texto completo de “Instalando Reanimated e valores compartilhados” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Native Academy, atualize para CoddyKit PRO. O curso de React Native Academy inclui 4 aulas no total.

O que vou aprender em “Instalando Reanimated e valores compartilhados”?

Instale react-native-reanimated, adicione o plugin do Babel, crie valores compartilhados com useSharedValue e conecte-os a estilos animados usando useAnimatedStyle. Você pratica React Native Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar React Native Academy?

Nenhuma experiência prévia é necessária. React Native Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Instalando Reanimated e valores compartilhados”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de React Native Academy?

Sim. Cada aula de React Native Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Instalando Reanimated e valores compartilhados
  2. Worklets e execução de código na thread da interface
  3. Gestos de arrastar e deslizar com Gesture Handler
  4. Pinçar para ampliar e girar
← Voltar para React Native Academy