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>
</>
);
};