Guides · 01
Values and style
Own a value in a component, derive outputs with calc(), and choose where the CSS variable is written.
Own a value
useAnimatedValue(initial) creates a Value owned by the component. Use a number, or a record such as { x: 0, opacity: 1 } whose fields are separate values.
In an ordinary style, a hook value is the token var(--kkwa-…, initial). Updates write that variable on the elements that use it; React does not render.
Preparing the example…
Derive with calc()
An interpolation without easing and add, subtract, multiply or divide by a constant become exact calc() expressions of the same variable. The browser derives them; no JavaScript runs for them per frame.
const progress = useAnimatedValue(0);
// A linear interpolation of a hook value is a calc() of the same CSS variable.
const x = progress.interpolate({ inputRange: [0, 1], outputRange: ['0px', '180px'] });
const half = multiply(progress, 0.5);
<div style={{ opacity: half, transform: `translateX(${x})` }} />;Preparing the example…
Colors and custom computations
Colors, eased interpolations, modulo, diffClamp and AnimatedComputed cannot be written as calc(). useAnimatedCSS(node) gives them their own CSS variable, updated by JavaScript, with the same component lifetime.
Using such a node directly in style throws, so the cost is never hidden.
const progress = useAnimatedValue(0);
// Colors and eased curves are not calc() expressions: give them their own CSS value.
const color = useAnimatedCSS(
progress.interpolate({ inputRange: [0, 1], outputRange: ['#3d3bf3', '#22b8f0'] }),
);
<div style={{ background: color }} />;Let the hook own a recipe
useAnimated(initial, factory, deps) owns the value and every controller declared synchronously in the factory. It starts on mount, restarts when a dependency changes and stops on unmount.
Pass { autoStart: false } for event-driven playback, then call start(), stop() or reset() on the returned value.
const intro = useAnimated(
{ opacity: 0, y: 24 },
(value) => {
parallel([
timing(value.opacity, { toValue: 1, duration: 400 }),
spring(value.y, { toValue: 0, stiffness: 220, damping: 20 }),
]);
},
[],
);
<section style={{ opacity: intro.opacity, transform: `translateY(calc(${intro.y} * 1px))` }} />;Write once for many elements
By default each element whose inline style uses the value receives the variable. With scope, the variable is written once on a container and inherited by its children: the right choice for hundreds of elements.
AnimatedProvider scope={ref} sets a default scope for every hook value below it.
const field = useRef(null);
// Written once on the field; every child that uses the value inherits it.
const wave = useAnimatedValue(0, { scope: field });
<div ref={field}>
{items.map((item) => (
<i key={item} style={{ transform: `rotate(calc(${wave} * 1turn))` }} />
))}
</div>;Read values in JavaScript
getValue() returns a snapshot without subscribing React. useAnimatedListener(node, fn) calls you on every change and removes the listener on unmount. Use it for canvas drawing or analytics, not for rendering.