ThreeJS sound keeps playing after moving to other page with React Link & UseEffect

I’m currently working on a project with ThreeJS and sound. I have a scene with different kind of object that have audio. All these objects are coming from a Firebase database. I use Mobx as statemanager. There is a button on the page to go to a different page. The problem I have is that when I go to this new page, the audio from the last page keeps playing. And when I come back to the first page, the audio is doubled.

This is the code I use:

React.useEffect(
  () =>
    autorun(() => {
      const createPins = () => {
        pinStore.pins.map((pin) => {
          let geo = new THREE.DodecahedronGeometry(1, 0);
          let mat = new THREE.MeshPhongMaterial({
            color: 16643437,
            shininess: 10,
            flatShading: true,
          });

          const pointer = new THREE.Mesh(geo, mat);
          scene.add(pointer);

          const audio = new THREE.PositionalAudio(listener);
          audioLoader.load("../../assets/audio/techno.mp3", (buffer) => {
            audio.setBuffer(buffer);
            audio.setLoop(true);
            audio.setRefDistance(3);
            audio.play();
          });
          pointer.add(audio);
        });
      };
    }),
  []
);

return (
  <>
    <Link to="/create">CREATE</Link>
  </>
);

Is there a way that when I go to a new page, the audio from the objects stop playing and when I come back to the page I hear the audio again.

Well, you just have to call audio.stop() when you navigate to another page. Figuring out the right point for calling this method depends on your UI library.

BTW: Do not load background music like techno.mp3 with AudioLoader. Doing so will download the entire file at once and transform it into an audio buffer. It’s better to stream the audio like so:

const mediaElement = new Audio( "../../assets/audio/techno.mp3" );
mediaElement.play();

audio.setMediaElementSource( mediaElement );

Never dealt with audio in react but maybe adding a return function to useEffect could help.

useEffect(() => {
  const yourAudio = getYourAudio()
  yourAudio.play()
  ....

  return () => { 
    yourAudio.pause()
    yourAudio.currentTime = 0
  }
}, [])

Did you manage to fix it?
I want to achieve exactly the same goal. Keep the audio playing of the first page when going to the second, and then reuse the previous audio (or reinitialise if necessary) of the first page when going back. But nomatter what I do (positionalAudioInstance.source.stop OR audioListenerInstance.context.close), the audio is always doubled and becomes a crackling sound.

Thnx

i take you you’re mixing imperative three with react, that is like react-dom and parts of the app go querySelector and addChild, you loose all integration and benefits that way. with react-three-fiber there’s no difference between scene and dom contents, routes are within the canvas and assets are managed and cached via react-suspense. hanging on to this or that asset or controlling state and side effects is the same as if you’d have to solve it in react-dom.

on top of that there are components and helpers for practically everything in drei.

side effect free positional audio: Lulaby city - CodeSandbox
routes: Router transitions - CodeSandbox