My goal was to make playing sounds in my React game easy and efficient. Using<audio> tags wasn't an option, because on mobile it creates huge delays between the action and the sound. I'm just starting with the Web Audio API, so please forgive me if I did something silly. It works though.
I decided to make it a React hook calleduseAudio():
import { useMemo, useCallback } from "react";const useAudio = (paths: Map<unknown, string>) => { const audioContext = useMemo( () => new AudioContext(), [] ); const arrayBuffers = useMemo( () => new Map([ ...paths ].map( ([ key, path ]) => [ key, fetch(path).then(response => response.arrayBuffer()) ] )), [paths] ); const decodedTracks = useMemo( () => new Map([ ...arrayBuffers ].map( ([ key, arrayBufferPromise ]) => [ key, arrayBufferPromise.then( arrayBuffer => audioContext.decodeAudioData(arrayBuffer) ) ] )), [arrayBuffers, audioContext] ); const play = useCallback( async (key: unknown) => { if (!decodedTracks.has(key)) { throw new Error("Invalid track key"); } const decodedTrack = await decodedTracks.get(key)!; const bufferSource = audioContext.createBufferSource(); bufferSource.buffer = decodedTrack; bufferSource.connect(audioContext.destination); bufferSource.start(); }, [audioContext, decodedTracks] ); return [ play ] as const;};export default useAudio;And here's how you'd use it in your app:
const audioFiles = new Map([ ["cat", "./audio/Meow.mp3"], [true, "https://pikachu.test/pikapika.wav"], // You can use any key you wish! [777, "./lucky.aac"],]);const Harmony = () => { const [ playAudio ] = useAudio(audioFiles); return ( <nav> <button type="button" onClick={() => playAudio("cat")} > Meow! </button> <button type="button" onClick={() => playAudio(true)} > Pika pika </button> <button type="button" onClick={() => playAudio(123)} > Gonna throw an error at ya! </button> </nav> );};I wanted to allow using any format of a key, hence usingMap ofunknown keys.
The main reason I'm asking for your reviews is to understand if I'm using Web Audio API correctly and if I could further optimize it, or perhaps I over-optimized something at the cost of clarity? I tried to memoize and reuse as much as I knew was possible.
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.

