问题
I'm using react-player to render youtube videos with map()
, like so:
class Jukebox extends Component {
constructor (props) {
super(props);
this.state = {
youtube_urls:[],
clients:[],
};
};
componentDidMount() {
if (this.props.isAuthenticated) {
this.getItems();
}
};
getItems(event) {
const {userId} = this.props
const options = {
url: `${process.env.REACT_APP_WEB_SERVICE_URL}/jukebox/${userId}`,
method: 'get',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': true,
Authorization: `Bearer ${window.localStorage.authToken}`
}
};
return axios(options)
.then((res) => {
console.log(res.data)
console.log(res.data.data)
this.setState({
clients: res.data.data[0].clients,
youtube_urls:res.data.data[0].youtube_urls
})
})
.catch((error) => { console.log(error); });
};
render() {
const { youtube_urls } = this.state;
return (
<div>
<h1 className="title is-1">Jukebox</font></h1>
{
clients.map((client, index) => {
/*
Obtain preview from state.previews for current artist index
*/
const audio = youtube_urls[index]
/*
Render current client data, and corresponding audio url
*/
return(
<div key={index}>
<ul>
<ReactPlayer
url={ audio }
controls
playing // <--- does not work
width='50'
height='150'
/>
<div className="Line" />
</ul></div>
)
})
})
};
According to to one the library props, playing
(see above), you can play media automatically when render finishes, but if I use map()
this will result in all videos playing at the same time.
At the same time, there is the callback prop onReady()
:
Called when media is loaded and ready to play. If playing is set to true, media will play immediately.
QUESTION:
How do I implement this and have all videos play, from index 0 on, one at at time, after all media is loaded?
回答1:
I'd use two state variables: videosLoadedCount
, playingIndex
. Initialize videosLoadedCount
at 0
and playingIndex
at -1
.
You can deduce the playing props from the playingIndex
state value.
Whenever there's an onReady, increment videosLoadedCount
. When it reaches the number of videos, you can increment playingIndex
. Whenever there is a onEnded
callback, you increment playingIndex
.
Something like this should work:
class Jukebox extends Component {
constructor(props) {
super(props);
this.state = {
loadedVideosCount: 0,
currentPlayingIndex: -1,
};
}
render() {
const { youtube_urls } = this.props;
const { loadedVideosCount, currentPlayingIndex } = this.state;
return (
<div>
{youtube_urls.map((url, index) => (
<ReactPlayer
url={url}
controls
onLoaded={() =>
this.setState(currentState => ({
loadedVideosCount: loadedVideosCount + 1,
currentPlayingIndex:
loadedVideosCount + 1 === youtube_urls.length ? 0 : -1,
}))
}
onEnded={() =>
this.setState(currentState => ({
currentPlayingIndex: currentPlayingIndex + 1,
}))
}
playing={index === currentPlayingIndex} // <--- does not work
width="50"
height="150"
/>
))}
</div>
);
}
}
来源:https://stackoverflow.com/questions/58793514/react-play-media-after-items-are-loaded-with-array-map