npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-hook-sound

v0.0.9

Published

A React hook for playing sounds.

Readme

react-hook-sound

A React hook for playing sounds.

Uses Howler.js under the hood.

One thing it adds on top of Howler.js is an optional per-second rate limit for each sound.

Not an exhaustive wrapper around Howler.js. Only implements features as needed.

Install

npm install react-hook-sound

Usage

To keep the hook simple, useCreateSoundPlayer only cares about the config object you pass in on mount. Dynamically changing the config object will not change the sounds; it's not supported.

import { useCreateSoundPlayer } from "react-hook-sound";

function Component() {
  const {
    playSound,
    stopSound,
    globalVolume,
    setGlobalVolume,
    globalMuted,
    setGlobalMuted,
  } = useCreateSoundPlayer({
    sounds: {
      chime: {
        src: ["/chime.mp3"],
        // Play at 50% of the global volume
        volume: 0.5,
      },
      bell: {
        src: ["/bell.mp3"],
        // Only 10 bells can be played per second
        rateLimit: 10,
      },
    },
  });

  return (
    <div>
      {/* Global volume control */}
      <label>
        <input
          type="range"
          value={globalVolume}
          onChange={(e) => setGlobalVolume(Number(e.target.value))}
        />
        <span>{globalVolume}</span>
      </label>

      <button
        onClick={() =>
          playSound("chime", {
            // Play at 25% of the global volume this one time
            volume: 0.25,
          })
        }
      >
        Play chime
      </button>
      <button onClick={() => playSound("bell")}>Play bell</button>
    </div>
  );
}

The intended usage is for you to pass in a static config object that maps all of the sounds you want to play in a top-level component like App.tsx or main.tsx, and then pass down the returned instance (or parts of it) to child components.

Option 1: Using createSoundPlayerContext() (Recommended)

The easiest way to share sounds across your app is with createSoundPlayerContext(), which creates a context provider and hook for you:

// sound.tsx
import { createSoundPlayerContext, Config } from "react-hook-sound";

type SoundKey = "click" | "win" | "lose";

const soundConfig: Config<SoundKey> = {
  sounds: {
    click: { src: ["/sounds/click.mp3"] },
    win: { src: ["/sounds/win.mp3"] },
    lose: { src: ["/sounds/lose.mp3"] },
  },
};

export const { SoundPlayerProvider, useSoundPlayer } =
  createSoundPlayerContext(soundConfig);

// App.tsx
import { SoundPlayerProvider } from "./sound";

function App() {
  return (
    <SoundPlayerProvider>
      <YourComponents />
    </SoundPlayerProvider>
  );
}

// AnyComponent.tsx
import { useSoundPlayer } from "./sound";

function AnyComponent() {
  const { playSound } = useSoundPlayer();
  return <button onClick={() => playSound("click")}>Click me</button>;
}

Option 2: Manual Context Setup

Alternatively, you can manually wire up context yourself:

// main.tsx

const SoundContext = createContext<ReturnType<typeof useCreateSoundPlayer> | null>(
  null
);

const SoundProvider = ({
  sound,
  children,
}: {
  children: React.ReactNode;
  sound: ReturnType<typeof useCreateSoundPlayer>;
}) => {
  return (
    <SoundContext.Provider value={sound}>{children}</SoundContext.Provider>
  );
};

const Root = () => {
  const sound = useCreateSoundPlayer({
    sounds: {
      chime: { src: ["/chime.mp3"] },
    },
  });

  return (
    <SoundProvider sound={sound}>
      <App />
    </SoundProvider>
  );
};

// Child.tsx

const ChildComponent = () => {
  const { playSound } = useContext(SoundContext);

  return <button onClick={() => playSound("chime")}>Play chime</button>;
};

Type safety

Here's how you can configure your sounds in one file and then export a common type for use in other files so that playSound can only be called with valid sound keys.

// sound.ts

import { useCreateSoundPlayer, Config, SoundPlayer } from "react-hook-sound";

type SoundKey = "bet" | "win";

export type MySoundPlayer = SoundPlayer<SoundKey>;

export const soundConfig: Config<SoundKey> = {
  sounds: {
    bet: {
      src: ["/bet.mp3"],
    },
    win: {
      src: ["/win.mp3"],
    },
  },
};

Now we can use soundConfig in our root component and pass playSound to a child:

// App.tsx

import { soundConfig, MySoundPlayer } from "./sound";

const App = () => {
  const { playSound } = useCreateSoundPlayer(soundConfig);

  return <Child playSound={playSound} />;
};

// Child.tsx

const Child = ({ playSound }: { playSound: MySoundPlayer["playSound"] }) => {
  return (
    <button
      onClick={() =>
        // playSound knows that "bet" is a valid sound key
        playSound("bet")
      }
    >
      Play bet
    </button>
  );
};

Volume Controls

The hook provides two levels of volume control:

  • Global volume: Affects all sounds played by the hook (setGlobalVolume)
  • Sound-specific volume: Set in the sound config or in playSound options

These volumes multiply together. For example, with globalVolume: 0.8 and playing a sound with volume: 0.5, the final volume will be 0.8 × 0.5 = 0.4 (40%).

Limitations

  • Not Dynamic: Sound configurations cannot be changed after mounting
  • Not a Complete Wrapper: Only implements a subset of Howler.js functionality
  • TypeScript Required: This library ships as TypeScript; it's not compiled to JavaScript