guide / vivus in react3 steps
vivus, as a hook.
vivus needs the mounted <svg>, so React code reaches for a ref and an effect, and has to remember to destroy the instance. svg-scroll-draw/vivus is a drop-in for vivus 0.4 with the same API, and its React entry does that wiring for you.
What goes wrong with the usual setup
- 1new Vivus() must run after the <svg> is in the DOM, so every component needs a ref and a useEffect.
- 2If the component unmounts mid-animation without destroy(), the animation-frame loop keeps running against detached paths; under StrictMode the effect also runs twice in development.
- 3vivus has not shipped since 0.4.6 (April 2021).
The switch, step by step
Step 01 · terminal
Switch the package — one command
Points every vivus import at the drop-in and swaps the dependency. Your new Vivus() calls keep working as they are.
terminalnpx svg-scroll-draw migrate --dry-run npx svg-scroll-draw migrate npm installStep 02 · Logo.jsx
Use the hook instead of ref + effect
useVivus returns the ref for your <svg> and the instance once it is ready. It destroys the instance on unmount. In Next.js, use it in a client component.
Logo.jsx'use client'; import { useVivus } from 'svg-scroll-draw/vivus/react'; export function Logo() { const [ref, vivus] = useVivus({ type: 'oneByOne', duration: 120 }); return ( <svg ref={ref} viewBox="0 0 120 40" onClick={() => vivus?.reset().play()}> <path d="M10 30 C 30 0, 60 0, 80 30" stroke="currentColor" fill="none" /> <circle cx="100" cy="20" r="12" stroke="currentColor" fill="none" /> </svg> ); }Step 03 · Hero.jsx
Want it to follow the scroll instead?
vivus plays on a clock. If the line should draw as the page scrolls — and reverse when it scrolls back — use ScrollDraw from the same package.
Hero.jsximport { ScrollDraw } from 'svg-scroll-draw/react'; <ScrollDraw easing="ease-out"> <svg viewBox="0 0 120 40">{/* paths */}</svg> </ScrollDraw>
What stays exactly the same
- new Vivus(element, options, callback) and every option, animation type and start mode.
- The output: shapes become the same <path>s with the same dash values — the browser test suite compares the SVG markup with vivus 0.4.6 exactly.
- Vivus.EASE and the other timing functions, and the data-start / data-duration / data-delay / data-async / data-ignore attributes.
Questions
Do I need to change my vivus options?
No. Pass the same options object to useVivus (or to new Vivus) as before.
How do I replay the animation?
The hook returns the instance: vivus.reset().play(), or play(-1) to run it backwards.
Does it respect reduced motion?
Yes. With prefers-reduced-motion: reduce, play() jumps straight to the end and still fires its callbacks.