因此,在我的一个项目中,我尝试将Spotify API中保存跟踪元素的功能添加到会话中,然后再次将它们拉出来。我插入了一个控制台日志,发现即使会话存储中的元素未定义,它仍然会在checkPlaylistName()
方法中输入if块。渲染语句中的控制台日志运行两次,第一次,它传递一个空数组,这是我想要的,没有传递任何元素,第二次,它由于某种原因传递undefined。这就是导致另一个组件出错的原因,说它是未定义的。如果您需要整个仓库,可以找到它here。否则,这是导致问题的代码:
import React from 'react';
import './App.css';
import SearchBar from '../SearchBar/SearchBar';
import SearchResults from '../SearchResults/SearchResults';
import Playlist from '../Playlist/Playlist';
import Spotify from '../../util/Spotify.js';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchResults: [],
playlistName: 'New Playlist',
playlistTracks: [],
term: ''
}
this.addTrack = this.addTrack.bind(this);
this.removeTrack = this.removeTrack.bind(this);
this.updatePlaylistName = this.updatePlaylistName.bind(this);
this.savePlaylist = this.savePlaylist.bind(this);
this.search = this.search.bind(this);
}
addTrack(track) {
const addingTrack = (track) => this.setState({playlistTracks: [...this.state.playlistTracks, track]});
addingTrack(track);
this.removeTrack(track, false);
sessionStorage.setItem("playlistTracks", this.state.playlistTracks);
}
removeTrack(track, removePlaylist) {
if(removePlaylist) {
const ids = this.collectIds(true);
let trackIndex = -1;
for(let i = 0; i < ids.length; i++) {
if (ids[i] === track.id) {
trackIndex = i;
}
}
if (trackIndex !== -1) {
const newPlaylist = this.state.playlistTracks;
newPlaylist.splice(trackIndex, 1);
this.setState({playlistTracks: newPlaylist});
this.search(this.state.term);
}
} else {
const ids = this.collectIds(false);
let trackIndex = -1;
for(let i = 0; i < ids.length; i++) {
if (ids[i] === track.id) {
trackIndex = i;
}
}
if (trackIndex !== -1) {
const newResults = this.state.searchResults;
newResults.splice(trackIndex, 1);
this.setState({searchResults: newResults});
}
}
sessionStorage.setItem("playlistTracks", this.state.playlistTracks);
}
collectIds(removePlaylist) {
let ids = [];
if(removePlaylist) {
this.state.playlistTracks.map(track => ids.push(track.id));
} else {
this.state.searchResults.map(track => ids.push(track.id));
}
return ids;
}
updatePlaylistName(name) {
this.setState({playlistName: name});
sessionStorage.setItem("playlistName", name);
}
savePlaylist() {
let trackURIs = [];
for(let i = 0; i < this.state.playlistTracks.length; i++) {
trackURIs.push(this.state.playlistTracks[i].uri);
}
Spotify.savePlaylist(this.state.playlistName, trackURIs);
this.setState({playlistName: 'New Playlist', playlistTracks: []});
sessionStorage.removeItem("playlistTracks");
sessionStorage.removeItem("playlistName");
}
async search(term) {
const results = await Spotify.search(term);
this.setState({searchResults: results});
const resultIds = this.collectIds(false);
const playlistIds = this.collectIds(true);
let indexes = [];
for(let i = 0; i < resultIds.length; i++) {
for(let j = 0; j < playlistIds.length; j++) {
if (resultIds[i] === playlistIds[j]) {
indexes.push(i);
}
}
}
if(indexes.length > 0) {
for (let k = 0; k < indexes.length; k++) {
results.splice(indexes[k], 1);
}
}
this.setState({searchResults: results});
this.setState({term: term});
}
checkTracks() {
if (sessionStorage.getItem("playlistTracks") !== undefined) {
const tracks = sessionStorage.getItem("playlistTracks");
this.setState({playlistTracks: tracks});
}
return this.state.playlistTracks;
}
checkPlaylistName() {
const savedName = sessionStorage.getItem("playlistName");
if (savedName !== null || savedName !== undefined) {
this.setState({playlistName: savedName});
console.log("hi");
}
return this.state.playlistName;
}
render() {
return (
<div id="root">
<h1>Ja<span className="highlight">mmm</span>ing</h1>
<div className="App">
<SearchBar onSearch={this.search} />
<div className="App-playlist">
<SearchResults searchResults={this.state.searchResults} onAdd={this.addTrack} onRemove={this.removeTrack} />
{console.log(this.checkTracks())}
<Playlist
playlistName={this.checkPlaylistName()}
playlistTracks={this.checkTracks()}
onRemove={this.removeTrack}
onNameChange={this.updatePlaylistName}
onSave={this.savePlaylist}
/>
</div>
</div>
</div>
);
}
}
export default App;
答案 0 :(得分:1)
setState函数是异步的(https://medium.com/@baphemot/understanding-reactjs-setstate-a4640451865b),因此你在checkTracks方法中返回旧状态。
解决方案: 不要在checkTracks方法中使用setState,使其成为:
if (sessionStorage.getItem("playlistTracks") !== undefined) {
return sessionStorage.getItem("playlistTracks");
}
return [];
在构造函数中使用此方法来定义状态。
同样以你的方式在渲染函数中设置状态(通过checkTracks方法)会导致无限循环。