Using the Chromium version of Edge: 93.0.961.38
I am building a music player app in React. When the user presses a button to select which show to listen to, it will auto-play an MP3 URL by rendering an <audio>
control with the autoPlay attribute set and a child <source>
element with the specified URL.
It all works fine when transitioning from nothing playing to the first selected show. But I want it to work such that if the user actively changes which show he listens to, it will auto play the newly selected show.
I can see from the console logging that when the other show button is pressed, that the <MediaPlayer>
element definitely re-renders using the newly selected URL. I even had it render the URL in the component itself. And I can see in the F12 tools (DOM inspector) that the src
property on the <source>
element is definitely updated. But the previous show keeps playing.
The almost good enough workaround is to introduce a STOP button that re-renders with no <audio>
control whatsoever. Then pressing the button for the other show definitely plays.
In the sample code below, click "Ambient" to start the first show. Then after it starts playing, click the "Heavy Metal" button. The "Ambient" music keeps playing. Click "Stop" then press "Heavy Metal" again - you'll hear the other show.
Is there a workaround? Or should I give up on using the built-in Audio DOM controls and use new Audio
with state?
import './App.css';
import {useState, createContext, useContext, useEffect, useMemo} from 'react';
const AMBIENT = "https://www.selbie.com/samples/atmospherics.mp3";
const METAL = "https://www.selbie.com/samples/wrekage.mp3";
const MediaPlayer = (props) => {
if (props.src) {
console.log("Url selected for playback: ", props.src);
}
else {
console.log("Nothing ready to play");
}
return (props.src ? (<div><audio controls autoPlay><source src={props.src} /></audio><br/>{props.src}</div>)
: (<div>Nothing yet to play</div>)
);
};
function App() {
const [show, setShow] = useState(null);
return (
<div>
<MediaPlayer src={show}/>
<p></p>
<button onClick={()=>setShow(AMBIENT)}>{"\u25B6\uFE0F Ambient"}</button><br/>
<button onClick={()=>setShow(METAL)}>{"\u25B6\uFE0F Heavy Metal"}</button><br/>
<button onClick={()=>setShow(null)}>{"\u23F9\uFE0F Stop"}</button><br/>
</div>
);
}
export default App;