Guides · 09
SSR, testing and production
Server rendering, hydration, tests and the cleanup rules you can rely on.
Server rendering
Hook values render their initial value into the server markup, and animation continues after hydration. React 18 and newer use useId for stable variable names; on React 16 and 17 servers, pass an id.
import { AnimatedProvider } from '@kkwaenggwari/animated';
// The package entry is marked 'use client'. A server layout can render the
// provider directly; hooks and Animated.<tag> go inside Client Components.
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<AnimatedProvider>{children}</AnimatedProvider>
</body>
</html>
);
}Stable ids on older React
Only needed when server rendering with React 16 or 17.
// React 18+ uses useId automatically. On React 16/17 servers, pass a stable id.
const progress = useAnimatedValue(0, { id: 'hero-progress' });Cleanup you can rely on
Everything a component owns is released with it.
useAnimated,useAnimatedValue,useTimelineanduseReorderstop their controllers and listeners on unmount.- Controllers and inputs declared in a
useAnimatedfactory are replaced together when a dependency changes. Animated.Keepremoves departing children after their motion, and a new pose interrupts from the current position.- Outside React,
bind,bindOutput,createTimelineandcreateLayoutScenereturn an explicitdispose.
Testing
flushAnimatedUpdates() applies pending output synchronously so deterministic tests can assert on the DOM.
import { flushAnimatedUpdates } from '@kkwaenggwari/animated';
act(() => progress.setValue(0.5));
flushAnimatedUpdates();
// Pending style writes are applied now; assert on the DOM.Text, attributes and properties
output(target, mapping) inside useAnimated owns a style, attribute, text or object-property output. bindOutput attaches the same mapping immediately and returns flush and dispose.
const label = useRef(null);
const count = useAnimated(
0,
(value) => {
output(label, { text: new AnimatedComputed([value], (v) => `${Math.round(v * 100)}%`) });
timing(value, { toValue: 1, duration: 1200 });
},
[],
);
<span ref={label} />;