Animating with React Native Skia

Lesson 3 of 6

Animated Values: useValue, useComputedValue & runTiming

Updating shape props from useState works, but every change re-renders the component. Skia has its own lightweight value system that updates the GPU surface directly, skipping React entirely, which is how you get smooth 60fps+ animation.

useValue

import { Canvas, Circle, useValue } from '@shopify/react-native-skia';

export function PulsingDot() {
  const radius = useValue(30);

  return (
    <Canvas style={{ flex: 1 }}>
      <Circle cx={100} cy={100} r={radius} color="#22d3ee" />
    </Canvas>
  );
}

radius is a mutable "Skia value" (a SkiaValue<number>), passing it straight into r tells Skia to re-read radius.current on every frame, changing radius.current = 50 updates the drawing immediately, with zero React re-render.

Animating with runTiming

import { runTiming, Easing } from '@shopify/react-native-skia';

runTiming(radius, 60, { duration: 500, easing: Easing.inOut(Easing.ease) });

runTiming(value, toValue, config) smoothly animates a Skia value from its current number to toValue over duration milliseconds, using the given easing curve, call it from a button press, a useEffect, or a gesture handler.

Deriving one value from another

useComputedValue recomputes automatically whenever a value it depends on changes, useful for keeping two animated properties in sync without duplicating the animation:

import { useComputedValue } from '@shopify/react-native-skia';

const opacity = useComputedValue(() => radius.current / 60, [radius]);

Here opacity always tracks radius, growing towards 1 as the circle grows towards its max radius, with no separate runTiming call needed for it.

📝 Animated Values Quiz

Passing score: 70%
  1. 1.What's the main advantage of a Skia useValue over React's useState for animation?

  2. 2.____ animates a Skia value from its current number to a target value over a given duration.

  3. 3.useComputedValue automatically recalculates whenever a Skia value it depends on changes.