我在 React 中遇到了一个非常烦人的错误,并认为它与调用不在我的组件 render
方法之一中的方法有关。我认为我提供了太多的代码,任何人都很难提供帮助,但让我尝试解释我的问题。
我正在进行一个返回 25 个项目的 API 调用。当用户单击“下一步”时,它应该更改背景并播放与背景相关的歌曲。这可行,但是当用户到达列表末尾时我想返回到第一首歌曲。背景图像返回,但播放了错误的歌曲。然后,当用户再次单击时,问题会自行纠正。
我认为问题是由 nextSong
方法中的这一行引起的。
this.audio.src = this.state.songs[this.props.song + 1];
请参阅下面的完整代码。如果有必要,我可以提供一个 github 链接,可以在其中克隆项目,这可能更容易调试。
我知道 SO 不是为了修复其他人的代码,但以防万一我错过了一些我想在这里询问的基本 react 知识。
var App = React.createClass({
getInitialState: function() {
return {
data: [],
song: 0
};
},
nextSong: function() {
if(this.state.song === this.state.data.length) {
this.setState({song : 0});
}else{
this.setState({song : this.state.song += 1});
}
},
previousSong: function() {
if(this.state.song === 0) {
this.setState({song : this.state.data.length});
}else{
this.setState({song : this.state.song -= 1});
}
},
getData: function(){
$.ajax({
url: '...',
method: 'GET',
success: function(response){
this.setState({data: response.items});
}.bind(this)
})
},
render: function() {
return(
<div>
<BackgroundImage src={this.state.data} image={this.state.song} />
<Button src={this.state.data} song={this.state.song} nextSong={this.nextSong} previousSong={this.previousSong} />
</div>
)
}
});
var BackgroundImage = React.createClass({
render: function() {
var images = this.props.src.map(function(photo, i){
return(photo.track.album.images[1].url)
})
var divStyle = {
background: 'url(' + images[this.props.image] + ')'
}
return(<div style={divStyle}></div>)
}
});
var Button = React.createClass({
getInitialState: function(){
return{
songs:[],
playing: false
}
},
audio: new Audio,
playSong: function(){
this.setState({playing: true});
this.audio.src = this.state.songs[this.props.song];
this.audio.play();
},
pauseSong: function() {
this.setState({playing: false});
this.audio.pause();
},
nextSong: function() {
this.audio.src = this.state.songs[this.props.song + 1];
this.audio.play();
},
onClickNext: function(){
this.setState({playing: true});
this.props.nextSong();
this.nextSong()
},
previousSong: function() {
this.setState({playing: true});
this.audio.src = this.state.songs[this.props.song - 1];
this.audio.play();
},
onClickPrevious: function(){
this.props.previousSong();
this.previousSong()
},
render: function() {
var self = this;
var songs = this.props.src.map(function(song, i){
self.state.songs.push(song.track.preview_url)
});
return (
<div className="button">
<div className="next" onClick={this.onClickNext}>
NEXT
</div>
<div className="pause">
<p onClick={this.state.playing ? this.pauseSong : this.playSong}></p>
</div>
<div className="prev" onClick={this.onClickPrevious}>
PREVIOUS
</div>
</div>
)
}
});
最佳答案
首先,你不应该这样做:
this.setState({song : this.state.song += 1});
因为这将首先设置 this.state.song 然后 setState,这可能会在您更新状态而不提醒 react 时产生一些冲突。我不确定 React 是否能正确处理这个问题。相反,只需执行以下操作:
this.setState({song : this.state.song + 1});
(与-=
相同)
回到问题:您应该只在一个地方跟踪当前歌曲。在这种情况下,您应该将其保留在 App 组件的状态中,而按钮组件则不应。 因此,像 nextSong 这样的方法在按钮组件中没有位置。 相反,您可以在 App 组件中更新歌曲(就像在 nextSong 方法中所做的那样),并通过 props 将当前歌曲直接传递到按钮组件。
然后,您可以使用生命周期方法 componentWillReceiveProps
检测当前歌曲是否发生变化,如下所示:
componentWillReceiveProps: function(nextProps) {
this.playSong(nextProps.song);
}
因此,当您更改 App 中的状态时,它会更新并将新的 props 传递给 Button,然后 Button 将使用新歌曲触发 componentWillReceiveProps 并执行其操作。
关于javascript - 从父组件状态传递时,react prop 未在正确的时间更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39780806/