Tonejs / Tone.js

A Web Audio framework for making interactive music in the browser.
https://tonejs.github.io
MIT License
13.4k stars 976 forks source link

Tone transport lags, then freezes with React #1006

Closed 03kkim closed 2 years ago

03kkim commented 2 years ago

Hi, so I was using Tone.js with React and Bulma CSS to create a simple metronome web app. I started off with a simple button that alternates color with every synthesizer note. However, the color switching slows down, and the audio seems to layer on top of itself until it completely cuts out. Here's my code:

https://codesandbox.io/s/angry-beaver-otf6h?file=/src/App.js

Without the changeButtonColor() call in the attackAndChangeColor() definition, the sound works fine. I couldn't find anything on this online so I'm posting it here.

Pbotsaris commented 2 years ago

Hey @03kkim, this is probably not a problem with tonejs.

I am not a react expert but I think you need to wrap your initialization code such as when you create loopA in a useEffect hook or move your tonejs code outside the component.

Everytime you update the state of buttonIsOn and buttonColor you are essentially re-rendering the whole component and consequently creating a new synth, synthA and loopA. There is so much that the browser can handle!

I hope this helps.

tambien commented 2 years ago

thanks for jumping in @Pbotsaris! i'm also not so familliar with React, but i agree that it seems like the issue is that you're creating new components on each render when you could be re-using the existing components.

03kkim commented 2 years ago

Hey @03kkim, this is probably not a problem with tonejs.

I am not a react expert but I think you need to wrap your initialization code such as when you create loopA in a useEffect hook or move your tonejs code outside the component.

Everytime you update the state of buttonIsOn and buttonColor you are essentially re-rendering the whole component and consequently creating a new synth, synthA and loopA. There is so much that the browser can handle!

I hope this helps.

After messing around with the code a bit and looking deeper into how useEffect works, I got the code working properly! Thanks for the detailed explanation!