Adding Sound FX to Your React Apps

William Le

In this article, learn how to incorporate sound effects in your React apps using a small library called uifx.

Sound effects aren’t used often for apps. You usually just see them on Big Tech’s apps like:

  • The iOS keyboard makes a wooden tap sound
  • Twitter iOS app makes a “boop” noise when you pull-to-refresh
  • “Hey Google” and “Hey Siri” have distinctive memed tones when you invoke their names

I think we’ve grown so accustomed to these “noises” that they’re not even considered interesting features anymore. But they are! Imagine if Apple suddenly decided to remove the “tick-tack” sound from their keyboard. For those of us who’ve gotten used to that familiar noise, we’d probably feel some kind of strange aural deprivation. Yet for web apps, we almost never see sound effects (sfx) built into the user interface and frankly… we almost don’t expect them to be there.

iOS/Android apps aren’t the only digital mediums that can express themselves with sounds. The web can… and should embrace sound effects more!

✨ Black Friday - 50% off all of Wes Bos' courses

Recommended React and GraphQL course

Introducing UIfx

I realized there were a lot of full-fledged audio libraries like SoundManager or Howler, but none of them were designed for UI sound effects which require a fire-and-forget strategy for playing mini-sound bites… so I built a simple library for this called uifx:

import UIfx from 'uifx';
import mp3File from './my-sounds/beep.mp3';

const beep = new UIFx({asset: mp3File});

<button onClick={beep.play}>Signup</button>

React is used here but you can use it in any JavaScript environment that has the Audio API –– which is most modern browsers!

Basic Usage

Here’s a practical example where sound fx is used to provide audio feedback on an <input type="range"/> element.

import React, { Component } from 'react';
import UIfx from 'uifx'; 
import tickAudio from './my-sounds/tick.mp3';

const tick = new UIfx({asset: tickAudio});

export default class InputRange extends Component {
  state = {
    value: 0,
  }
  onChange = (event) => {
    this.setState({ value: event.target.value });
    tick.play();
  }
  render() {
    return (
      <div>
        <div>{this.state.value}</div>
        <input
          type="range"
          value={this.state.value}
          onChange={this.onChange}
        />
      </div>
    )
  }
}

Don’t you get a mental picture of a watchmaker’s tool or something? How interesting is that?! Audio adds a completely new sensory experience!

Throttling Playback

UIfx is designed specifically for playing tiny audio files in rapid succession. Sometimes, however, you’ll want to throttle playback a bit so it doesn’t sound too crazy or overload the user’s speakers:

const tick = new UIfx({
  asset: tickAudio,
  throttleMs: 40
})

Finding the right balance of realtime feedback is more an art rather than a science. I usually try to put myself in user’s shoes and ask myself how much instant audio feedback I would want, and throttle accordingly.

Changing playback volume

By default, sounds will play at full volume. To change the volume of a UIfx sound, call UIfx.setVolume() method:

beep.setVolume(0.8).play();

// or...

beep.setVolume(0.8);
beep.play();

Valid arguments are 0.01.0 to emulate the Audio api. In the demo below the volume is changed using the previous <input type="range"> slider:

class ToastNotifications extends Component {
  state = {
    isToastVisible: false,
    volume: 0.5,
  }
  sfx = {
    beep: new UIfx({asset: beepAudio}),
    tick: new UIfx({asset: tickAudio, throttleMs: 100}),
    appear: new UIfx({asset: appearAudio}),
    disappear: new UIfx({asset: disappearAudio})
  }
  onVolumeChange = (event) => {
    this.setState(
      { volume: event.target.value },
      // "setState" cb to get updated volume 👇
      () => this.sfx.tick.setVolume(this.state.volume).play()
    )
  }
  toggleToast = () => {
    this.setState(
      { isToastVisible: !this.state.isToastVisible },
      () => {
        this.state.isToastVisible  // 👈 decide which sfx to play
          ? this.sfx.appear.setVolume(this.state.volume).play()   
          : this.sfx.disappear.setVolume(this.state.volume).play()
      }
    )
  }
  render() {
    return (
      <div>
        
        <button onClick={this.toggleToast}>
          Toggle notification
        </button>

        <div>
          Volume: {this.state.volume}
        </div>
        <input
          value={this.state.volume}
          onChange={this.onVolumeChange}
          min="0.0"
          max="1.0"
          step="0.01"
          type="range"
        />

        <Toast isVisible={this.state.isToastVisible}/>

      </div>
    )
  }
}

If you don’t want to persist volume changes, you can easily play at a different volume by passing an argument to UIfx.play():

const tick = new UIfx({
  asset: tickMp3,
  volume: 1.0
});

tick.play(0.25); // plays at 0.25 volume
tick.play(); // plays at 1.0 volume

Conclusion

Sound effects in web apps is a relatively unexplored domain. My hope is that uifx will help you build apps that engage people more fully –– both visual and aural. Small touches like this can touch people’s hearts and provide more richer exeriences to your users.

📦 Check out uifx! I'd love to know what you think!

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#