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.

importvivussvg-scroll-draw/vivus
version0.4.6 · 20212.23.3 · maintained
licenceMIT=MIT
gzip4.1 KB4.2 KB
in ReactYour own effectuseVivus
Fig. 1 — what changes, measured
01The problem

What goes wrong with the usual setup

  1. 1new Vivus() must run after the <svg> is in the DOM, so every component needs a ref and a useEffect.
  2. 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.
  3. 3vivus has not shipped since 0.4.6 (April 2021).
023 steps

The switch, step by step

  1. 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.

    terminal3 lines
    npx svg-scroll-draw migrate --dry-run
    npx svg-scroll-draw migrate
    npm install
  2. Step 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.jsx12 lines
    '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>
      );
    }
  3. 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.jsx5 lines
    import { ScrollDraw } from 'svg-scroll-draw/react';
    
    <ScrollDraw easing="ease-out">
      <svg viewBox="0 0 120 40">{/* paths */}</svg>
    </ScrollDraw>
03unchanged

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.
04questions

Questions

Q1

Do I need to change my vivus options?

No. Pass the same options object to useVivus (or to new Vivus) as before.

Q2

How do I replay the animation?

The hook returns the instance: vivus.reset().play(), or play(-1) to run it backwards.

Q3

Does it respect reduced motion?

Yes. With prefers-reduced-motion: reduce, play() jumps straight to the end and still fires its callbacks.

05More guides

More migration guides