Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Use-sound, a React hook for sound effects on the web (joshwcomeau.com)
131 points by joshwcomeau on March 30, 2020 | hide | past | favorite | 31 comments



I've been following your site for a few weeks, and I just love it. The design, the writing, the interactive examples, the little sounds... it's all so thoughtful!

I'm thinking of switching to Gatsby so I can have more fun with these kinds of things. I write electronic music in my spare time, so adding a few sound effects sounds like an ideal afternoon! :)


Why is switching to Gatsby a requirement to have fun with these types of things?


Oh, it’s definitely not a requirement. But having MDX support, CSS modules, and React’s componentization would make the development experience a lot nicer.


This is cool but, oh boy, a mute button that makes a sound when you click it is user hostile.


Reminds me of the days when the iPhone only did ringer volume unless sound was playing. In meetings you’d panic and have to ramp the volume way down after it starts blasting out.


I run all tabs muted by default - I find sound effects on the web to be rather frustrating. Especially combined with autoplay.


FF disables autoplay by default


This is really cool & you have a great website! The one thing I don’t quite understand is why this needs to be a React hook per se - couldn’t it just be a normal library function that you call inside your component?


If you want to be able to keep a handle on a playing sound so that you can stop it or do other things, you've got state. So this is like an audio version of useState.


Right, so the reasons this needs to be a hook:

- As someone else said, it manages playback state. This is technically managed by a third-party library, but we expose an `isPlaying` boolean which is held in React state

- It lazy-loads Howler, the underlying audio dependency. This means the bundle cost is ~1kb instead of 11kb (gzip)

- It memoizes all the callback functions to avoid breaking React.memo / PureComponent components


I am very glad this post starts by acknowledging that sound on the web is frequently annoying.


Yeah! And I love that we can explore every nook and cranny without a lot of "oh wow why would you ever want this?!" Stuff like this is super useful for the countless non-standard web tech usages, such as making a card game in react.


Not to nitpick, but I'm wondering about the tradeoffs of adjusting volume/playback rate in an effect (https://github.com/joshwcomeau/use-sound/blob/master/src/ind...). I'm kind of wondering how this works in a concurrent mode world when there are other, higher priority things React is deferring reconciliation/effects for.


You have control over the priority of things in concurrent mode. So long as your component doesn't suspend and it's not in a transition then it'll update as soon as possible (basically what happens in React now). https://reactjs.org/docs/concurrent-mode-patterns.html#split...


Really cool. Also, the showcase website is made really well, kudos.


I was hoping to see the source for the lib, but I can't find it in the npm package listing. Anyone manage to track it down?


It's linked in the article: https://github.com/joshwcomeau/use-sound


Ok not working on iOS safari for me, but that’s not your fault... I had a howler based app that seemed to work 6 months ago and after some update stopped working on iOS (no more sound!). I wonder if anyone knows why.


Could some one clarify for me why the consts for the useSound() are declared inside an array?

const [play] = useSound()


Other commenters beat me to it, but yeah, it's an ergonomics thing. If you have multiple sounds, you can do:

const [playBell, bellOptions] = useSound();

const [playBoom, boomOptions] = useSound();

It follows the convention of other React hooks, like useState.


It's the pattern/convention that the React team used for the built-in hooks.

const [ myState, setMyState ] = useState(initalValue);

In this case, the "play" is a function to play the sound, and the next array argument is an object with more useful parameters.

const [ play, args ] = useSound()

I assume it's a workaround/replacement for returning a tuple in vanilla JavaScript.


useSound returns an array (used like a tuple here).

The syntax you see here is Array Destructuring. This way you access the 0th element directly.

Equivalent of:

const hook = useSound() const play = hook[0]

If you want to just take the 2nd item, you can destructure like this: const [, pause] = useSound().


When all you have is a hammer...


what?


When all you have is a hammer everything looks like a hook.


Is there a way to do all of this with CSS only ?


Or emojis?


I wish I could think of a leveled way to speak my mind but gosh, there's something about all this that really makes me want to throw up.

The idea of adding a tiny little button that makes a sound is innocent. It's a single button after all, isn't it? The thing is, once you share this idea, it has a risk of going to all of the pages. Websites everywhere are already full of distractors that make them annoying to browse for people with limited attention. Once you also add sounds, you might hit several problems you might have not thought of:

1. the tab is opened in the background and the user is trying to find the one that's using the speaker, 2. the volume is mismanaged because some other tab is playing their sounds too silently and yours will make the user's ears explode, 3. (probably some more that I hadn't thought of)

At first it just felt like a chunch, but then I saw another IMHO not-so-great idea coming from the user - the sticky navbar at the top is partially transparent, effectively taking even more screen estate. Probably looks shiny, but also makes your website hard to read. It really does feel like some hostile design.

It really looks like we're back to 90s', with a new generation of equivalents of <marquee> tags, annoying GIFs, mismatched colors and "still in development" signs. Thing is, this generation is sugar-coated and seems shiny at first, until you realize that every single web 4.0 page is making you nauseated. After all, it's legitimate to put on a GDPR consent overlay covering 90% of your smartphone and do other shitty moves other people do anyway, right? Though I have to admit I appreciate that this at least this one wasn't to be found on your website.

I mean, excuse the rant... as much as I appreciate open sourcing your work and hoping to improve something on the net, consider effects on users' sanity this change will bring. In the meantime, I wish I could anti-star your project, as an example of where I don't want the web to go.


It appears to me that you are very strongly projecting your fears based on past experience into the future.

This can already be managed at the browser layer (we didn't use to have a mute control on the tab before), and those controls will likely be tightened in the unlikely case that this still gets out of hand.

As mentioned by OP, please don't throw the baby out with the bathwater. Web experiences aren't designed like they were in the wild west of the nineties anymore. This is for very specific kinds of experiences - as you know, the web is an app platform nowadays, so certain experiences can clearly benefit from this without ruining anyone's day.

I actually agree with you about the sticky navbar - though also with caveats.

The core point of all UX design is context. In some situations you have the real estate to play with and the sticky navbar can actually support more fluid navigation.

When there is less screen real estate, you should be responsible and detect it. Not everyone will. That's okay, they will pay the price every bad design pays in the market - loss of customers.


God forbid I want to create a little game with sound effects using React.

This is a great little tool!


I agree. We should also remove the img tag and the entirety of CSS. They can be used to make the user experience worse (according to me and no one else), so they shouldn't exist.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: