React quickstart

The canvas below is a real, running React component — not a screenshot — built entirely on useSineWaveGenerator.

The component

No JSX build step required to read this — the live demo above is compiled from exactly this file, using React.createElement directly.

import React from "react";
import { createRoot } from "react-dom/client";
import { useSineWaveGenerator } from "@sebastienrousseau/sine-wave-generator/use-sine-wave-generator";

const SineWaveDemo = () => {
  const { canvasRef } = useSineWaveGenerator({
    waves: [
      { amplitude: 22, wavelength: 140, speed: 0.05 },
      { amplitude: 14, wavelength: 100, speed: 0.06, strokeStyle: "rgba(168, 85, 247, 0.5)" },
    ],
  });
  return <canvas ref={canvasRef} style={{ width: "100%", height: "220px" }} />;
};

createRoot(document.getElementById("root")).render(<SineWaveDemo />);

Install

npm install @sebastienrousseau/sine-wave-generator react

react is an optional peer dependency — it's only required if you import use-sine-wave-generator. The rest of the package works with zero dependencies in any framework, or none at all.

The hook's API

useSineWaveGenerator(options) creates the generator on mount and destroys it on unmount, returning two refs:

const { canvasRef, generatorRef } = useSineWaveGenerator({
  waves: [{ amplitude: 26, wavelength: 120, speed: 0.8 }],
});

// canvasRef  — attach to your <canvas>
// generatorRef.current — the live SineWaveGenerator instance;
//   call .addWave(), .syncToAudio(), .setQuality(), etc. imperatively

Two more common patterns

The hook is the same every time: only the options and what you do with generatorRef change.

Hero background

const HeroBackground = () => {
  const { canvasRef } = useSineWaveGenerator({
    autoResize: true,
    waves: [
      { amplitude: 16, wavelength: 220, speed: 0.06, strokeStyle: "rgba(94, 234, 212, 0.35)" },
      { amplitude: 10, wavelength: 160, speed: 0.04, strokeStyle: "rgba(168, 85, 247, 0.25)" },
    ],
  });
  return <canvas ref={canvasRef} style={{ width: "100%", height: "160px" }} />;
};

Audio-reactive (microphone)

This is where generatorRef earns its keep: the hook only creates the generator once, so anything audio-driven is wired up imperatively through the ref, on your own event (a button click, not mount):

const AudioReactive = () => {
  const { canvasRef, generatorRef } = useSineWaveGenerator({
    waves: [{ amplitude: 10, wavelength: 140, speed: 0.03 }],
  });

  const startListening = async () => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    const audioSync = new AudioSync();
    audioSync.connect(stream);
    generatorRef.current.syncToAudio(audioSync, {
      amplitude: { source: "energy", intensity: 2 },
    });
  };

  return (
    <>
      <canvas ref={canvasRef} style={{ width: "100%", height: "160px" }} />
      <button onClick={startListening}>Start listening</button>
    </>
  );
};