在本地保存和重新加载值的问题

时间:2018-02-23 20:42:25

标签: javascript reactjs session-storage

因此,在我的一个项目中,我尝试将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;

1 个答案:

答案 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方法)会导致无限循环。