用componentDidUpdate()和React-APlayer库更新状态。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用componentDidUpdate()和React-APlayer库更新状态。相关的知识,希望对你有一定的参考价值。
我正试图用从父组件中的fetch请求中接收到的数据更新状态。我使用的是'react-aplayer'库 (https:/github.comMoePlayerreact-aplayer。)作为一个音频播放器。
我能够将歌曲硬编码到播放列表中,如下面的'this.state.audio'所示。 然而,当我试图通过componentDidUpdate()方法将这些数据改为通过道具接收的数据时,我无法将State设置为新数据。当我控制台.日志'this.state.audio'查看数据时,我得到两条消息:第一条是硬编码的播放列表信息,下一条是我从fetch请求中接收到的数据。
我如何用新的数据更新状态,使其取代硬编码的数据?
这是我的组件。
import React, { PureComponent, Fragment } from 'react';
import ReactAplayer from '../react-aplayer';
import './AudioPlayer.css';
export default class AudioPlayer extends React.Component {
constructor(props){
super(props);
this.state = {
theme: '#F57F17', //#F57F17,
lrcType: 3,
audio: [
{
name: "Song Title",
artist: 'Artist Name',
url: 'https://dl.dropbox.com/s/os8v0ymru1433nn/2%20mix.wav',
cover: 'https://images.pexels.com/photos/617278/pexels-photo-617278.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
lrc: '',
theme: '#46718b'
},
{
name: "Next Song Title",
artist: 'Next Artist Name',
url: 'https://dl.dropbox.com/s/os8v0ymru1433nn/2%20mix.wav',
cover: 'https://images.pexels.com/photos/617278/pexels-photo-617278.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
lrc: '',
theme: '#46718b'
}
]
};
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.playlist !== prevProps.playlist) {
const songs = this.props.playlist;
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 })
this.setState({sample: 'hello'})
}
}
// 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('audio state', this.state.audio)
const props = this.state;
return (
<Fragment>
<div className="landing">
<div className="aplayer-wrap">
{/* example with detailed props */}
<ReactAplayer
{...this.state}
onInit={this.onInit}
onPlay={this.onPlay}
onPause={this.onPause}
/>
</div>
</div>
</Fragment>
);
}
}
这是调用库中的react -aplayer组件。
import React from 'react';
import PropTypes from 'prop-types';
import APlayer from 'aplayer';
import 'aplayer/dist/APlayer.min.css';
import events from './events';
const capitalize = function(str) {
return str[0].toUpperCase() + str.slice(1);
};
const eventsPropTypes = events.reduce((acc, event) => {
acc[`on${capitalize(event)}`] = PropTypes.func;
return acc;
}, {});
const audioItemShape = PropTypes.shape({
name: PropTypes.string,
artist: PropTypes.string,
url: PropTypes.string,
cover: PropTypes.string,
lrc: PropTypes.string,
theme: PropTypes.string,
type: PropTypes.string
});
class ReactAplayer extends React.Component {
static propTypes = {
onInit: PropTypes.func,
// belows are the same props with aplayer
fixed: PropTypes.bool,
mini: PropTypes.bool,
autoplay: PropTypes.bool,
theme: PropTypes.string,
loop: PropTypes.oneOf(['all', 'one', 'none']),
order: PropTypes.oneOf(['list', 'random']),
preload: PropTypes.oneOf(['auto', 'metadata', 'none']),
volume: PropTypes.number,
audio: PropTypes.oneOfType([
audioItemShape,
PropTypes.arrayOf(audioItemShape)
]),
customAudioType: PropTypes.object,
mutex: PropTypes.bool,
lrcType: PropTypes.number,
listFolded: PropTypes.bool,
listMaxHeight: PropTypes.string,
storageName: PropTypes.string,
// belows are bind event listener
...eventsPropTypes
};
static defaultProps = {
onInit() {},
fixed: false,
mini: false,
autoplay: false,
theme: '#b7daff',
loop: 'all',
order: 'list',
preload: 'auto',
volume: 0.7,
mutex: true,
lrcType: 0,
listFolded: false,
storageName: 'react-aplayer-setting'
};
componentDidMount() {
const { onInit, ...restProps } = this.props;
const control = new APlayer({
...restProps,
container: this.container
});
events.forEach(event => {
const funcName = 'on' + capitalize(event);
const callback = this.props[funcName];
if (callback) {
control.on(event, callback);
}
});
this.control = control;
onInit(control);
}
render() {
return <div ref={el => (this.container = el)} />;
}
}
export default ReactAplayer;
经过来回的评论,似乎这可能是React本身如何看待你的道具和更新顺序的问题。
如果你坚持从道具中更新你的状态,那么我建议使用更安全的方法。getDerivedStateFromProps
方法,该方法是为了解决你所面临的问题而引入的。
从道具更新状态 (何时使用,为何有此方法)
第二种方法是只用道具来渲染你的播放列表,然后传入你喜欢的任何初始播放列表。(我个人比较喜欢这种方法)
以上是关于用componentDidUpdate()和React-APlayer库更新状态。的主要内容,如果未能解决你的问题,请参考以下文章
componentDidUpdate 中的 prevState 是 currentState?
mapStateToProps,但未调用componentDidUpdate