Reputation: 2252
I have a HTML Audio tag in a ReactJS component. A component gets rendered for every different audio file. The first time the component gets rendered correctly, an audio displays along with the length of the file, but when I select another file to be rendered, it doesn't render even though the source code indicates the path to that file I selected.
<audio controls><source src={props.audio} type="audio/wav"></source></audio>
where "props.audio" is the path to the audio file, this code is inside my ReactJS component which gets rendered every time a user selects a different file.
For example if I have two audio files, one 5 minutes long and the 2nd one 10 minutes long, and I select the first audio, the audio displays 5 minutes and I could play. However, when I select the 2nd audio file, the audio tag doesn't get rerendered and it still plays the 1st audio file. Although when I check the source code, it indeed is the right path to the file.
What's going on here and any ideas on why it's not rendering the new audio recording correctly after the first time?
Upvotes: 1
Views: 2883
Reputation: 13689
As suggested by Avinash Chovatiya, just add a 'key' attribute to force the browser to create a new element in DOM.
<audio key={props.audioUrl} controls>
<source src={props.audioUrl} type="audio/wav" />
</audio>
Upvotes: 0
Reputation: 1
This is because the browser does not rerender the media element even when the src attribute is changed in the source element inside the media element.
This is not the problem with React but because of the browser's behavior.
For now, you add the key attribute to the audio element which forces the browser to create a new element in the DOM.
Upvotes: 0
Reputation: 1895
Found this spec note on why this happens. Use this solution if calling audio.load()
within your UI framework of choice causes render loop.
..modifying a source element and its attribute when the element is already inserted in a video or audio element will have no effect. To change what is playing, just use the src attribute on the media element directly
<audio>
<source src='./first-src'/>
</audio>
To change the src
<audio src='./second-src'/>
<source src='./first-src'/>
</audio>
Upvotes: 2
Reputation: 59456
According to this question, apparently the problem is that audio.load()
should be called after audio.src
is changed, otherwise it doesn't "detect" the change. If that's your only problem, so here's the solution:
1) Make sure your audio component only has 1 prop, the audio one
This is important because we will call this.refs.audio.load()
every time the component re-renders and we don't want to call it when it re-render for a reason other than the audio
prop changing. There are other work-arounds for this but let's stick with this one for the sake of simplicity. If your current Audio component has other props, be sure to isolate it in a separate component.
2) Render the ref in the audio tag
render() {
return <audio ref="audio"/>;
}
3) Prevent re-rendering if the audio
prop didn't change
shouldComponentUpdate(nextProps, nextState) {
return nextProps.audio != this.props.audio)
}
4) Call this.refs.audio.load
when the component updates
componentDidUpdate() {
this.refs.audio.load();
}
Upvotes: 4