Custom Reack Hooks: useAudio

In the last episode of the Custom React Hooks series, we’ve discovered the useNetworkState hook to simplify the user’s network state management. Today, we’ll explore another useful custom hook: useAudio. Ready? Let’s go!

Motivation
Implementation
Usa…


This content originally appeared on DEV Community and was authored by Ludal 🚀

In the last episode of the Custom React Hooks series, we’ve discovered the useNetworkState hook to simplify the user’s network state management. Today, we’ll explore another useful custom hook: useAudio. Ready? Let’s go!

Motivation

Why would you ever need such a hook? We’ll, I’ll give you two examples. The first one is my personal website, iamludal.fr (I swear this is not self-promotion 🙄), built with React, which top navigation bar contains a button to switch between light and dark theme. Actually, if you turn up the sound a little bit, you might hear a switch sound. This sound comes from this custom hook. The second example is the Typospeed game (not self-promotion either), where you can hear sounds when removing a word (actually, Typospeed was built with Svelte, but you get the idea). In both examples, we need to play some sounds, and we don’t want to repeat ourselves by manually instantiating a new audio, settings its volume, its playback rate...

const Home = () => {
  const audio = useRef(new Audio('/switch.mp3'))

  useEffect(() => {
    audio.current.playbackRate = 1.5
    audio.current.volume = 0.8
  }, [])

  return (
    <button onClick={audio.current.play}>Play Sound</button>
  )
}

👎 We don’t want write all this code every time we need to use audio sounds. Also, we have to use the useRef hook in this situation and keep track of its current value in order to not recreate the audio instance at each component re-render.

That being said, we now have a sufficient reason to implement our new custom hook. Let’s get our hands dirty! 👨🏻‍💻

Implementation

As we said in the previous part, we don’t want to repeat ourselves (and this is the major goal of custom hooks). Therefore, our function will take optional parameters for our audio instance (which can be either static or dynamic), corresponding to additional options.

const audio = useAudio('/switch.mp3', { volume: 0.8 })

Also, we don’t want to bother with the .current property: we have to extract this logic inside the new hook. This way, we will be able to interact with the audio instance directly.

audio.play()
audio.pause()

Hence the skeleton will look like this:

const useAudio = (src) => {
  const audio = useRef(new Audio(src))

  return audio.current
}

This is the first and basic version of the hook. If you don’t need to have additional options, you’re ready to go. But we will add another parameter to this hook: an options object. Each time a given property of that object changes, we have to update our instance. This way, the options can be updated dynamically from outside — with another hook, such as useState. The final hook implementation now looks like this:

const useAudio = (src, { volume = 1, playbackRate = 1 }) => {
  const audio = useRef(new Audio(src))

  useEffect(() => {
    audio.current.volume = volume
  }, [volume])

  useEffect(() => {
    audio.current.playbackRate = playbackRate
  }, [playbackRate])

  return audio.current
}

ℹ️ If you need any other options, feel free to add them depending on your needs. For instance, you could add an array parameter for the play method in order to only play a specific part of the audio (particularly useful when you have one audio file with multiple sounds, which is a technique used by some games).

Our hook is now ready to be used. 🤘

Usage

Back to our first example, the code can now be simplified as follows:

const Home = () => {
  const audio = useAudio('/switch.mp3', { volume: 0.8, playbackRate: 1.5 })

  return (
    <button onClick={audio.play}>Play Sound</button>
  )
}

We’ve abstracted out all the logic inside this new hook, which leads to a simpler, cleaner and more readable code.

Conclusion

I hope this hook will be useful to you for your projects. If you have any questions, feel free to ask them in the comments section. With that being said, thank you for reading me, and I’ll see you next time for a new custom hook. 🤗

Source code available on CodeSanbox.

Support Me

If you wish to support me, you can click the following link to buy me a coffee (which I will then probably turn into a new custom hook... ☕).

Buy me a coffee


This content originally appeared on DEV Community and was authored by Ludal 🚀


Print Share Comment Cite Upload Translate Updates
APA

Ludal 🚀 | Sciencx (2022-01-11T15:44:59+00:00) Custom Reack Hooks: useAudio. Retrieved from https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/

MLA
" » Custom Reack Hooks: useAudio." Ludal 🚀 | Sciencx - Tuesday January 11, 2022, https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/
HARVARD
Ludal 🚀 | Sciencx Tuesday January 11, 2022 » Custom Reack Hooks: useAudio., viewed ,<https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/>
VANCOUVER
Ludal 🚀 | Sciencx - » Custom Reack Hooks: useAudio. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/
CHICAGO
" » Custom Reack Hooks: useAudio." Ludal 🚀 | Sciencx - Accessed . https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/
IEEE
" » Custom Reack Hooks: useAudio." Ludal 🚀 | Sciencx [Online]. Available: https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/. [Accessed: ]
rf:citation
» Custom Reack Hooks: useAudio | Ludal 🚀 | Sciencx | https://www.scien.cx/2022/01/11/custom-reack-hooks-useaudio/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.