I am attempting to render playlist information for an Audio Player in React. The data is coming from a fetch call in the parent component (PostContent.js). The data being returned is an array of objects that looks like: [ {name: 'track name', artist: 'artist name', url: ' https://blahblah.wav ', lrc: 'string', theme: 'another string' }, {…}, {…}, etc. }
I am not able to return the data in the render() method of the child component (AudioPlayer.js). When I console.log(this.props.audio) in the render(), my terminal prints three responses. The first is an empty array, and the next two are the correct data that I need (an array of objects).
How can I set the props on the 'audio' key in the 'props' object in the render() method of the AudioPlayer.js component?
I should mention that I am using the react-aplayer library, and I am able to make this work with hard-coded data, as in the example here ( https://github.com/MoePlayer/react-aplayer ), but I am trying to make a dynamic playlist component for a blog website. Any advice is greatly appreciated.
AudioPlayer.js (Child Component)
import React, { PureComponent, Fragment } from 'react';
import ReactAplayer from '../react-aplayer';
import './AudioPlayer.css';
import sample from '../../src/adrian_trinkhaus.jpeg';
export default class AudioPlayer extends React.Component {
// event binding example
onPlay = () => {
console.log('on play');
};
onPause = () => {
console.log('on pause');
};
// example of access aplayer instance
onInit = ap => {
this.ap = ap;
};
render() {
console.log('props in render of AudioPlayer', this.props.audio)
const props = {
theme: '#F57F17',
lrcType: 3,
audio: this.props.audio
};
return (
<div>
<ReactAplayer
{...props}
onInit={this.onInit}
onPlay={this.onPlay}
onPause={this.onPause}
/>
</div>
);
}
}
PostContent.js (Parent Component)
import React, { Component, useState, Fragment } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import AudioPlayer from './AudioPlayer';
export default class PostContent extends Component {
constructor(props) {
super(props);
this.state = {
id: '',
episodeData: [],
audio: []
}
}
async componentDidMount() {
const { id } = this.props.match.params;
const response = await fetch(`http://localhost:5000/episode/${id}/playlist`);
const jsonData = await response.json();
const songs = jsonData;
const audio = Object.keys(songs).map(key => {
return {
name: songs[key].name,
artist: songs[key].artist,
url: songs[key].url,
cover: songs[key].cover,
lrc: songs[key].lrc,
theme: songs[key].theme
}
});
this.setState({ audio })
}
componentDidUpdate(prevProps, prevState) {
if (prevState.audio !== this.state.audio) {
const newAudio = this.state.audio;
this.setState({ audio: newAudio }, () => console.log('new audio', this.state.audio))
}
}
render() {
return (
<Fragment>
<AudioPlayer audio={this.state.audio} />
<Link id='home-link' to='/' activeClassName='active'>Homepage</Link>
{this.state.episodeData.map((item, i) => (
<div key={i} className="word-content">
<h2 className="show-title">{item.post_title}</h2>
<div className="episode-post-content">
<p>{item.post_content1}</p>
<p>{item.post_content2}</p>
<p>{item.post_content3}</p></div>
</div>
))}
<Table data={this.state.data} />
<div className="bottom-link">
<Link id='home-link' to='/' activeClassName='active'>Homepage</Link>
</div>
</Fragment>
)
}
}
Actually I think it doesnt work because you set this.props inside a props obejct, so maybe you need to do something like
var that = this
const props = {
audio = that.props.audio
}
i played around with an async scenario with your code on codesandbox
i think the problem is when you're trying to access the payload in ReactAPlayer
component when audio it's not loaded yet from the async call. what you need to do is only use "audio" when it's valid like this if (audio.length) {...}
or audio &&...
some form of check to prevent it from being accessed in the reactAplayer render function.
fyi - you can remove the componentDidUpdate
hook, since you have a setState
call inside the...Didmount hook, when setState
is called inside...didMount, the component calls its render()
thus trigger a child re-render and its child will do the same..
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.