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

标签 javascript reactjs session-storage

因此,在我的一个项目中,我尝试添加将轨道元素从 Spotify API 保存到 session 中,然后再次拉取它们的功能。我插入了一个控制台日志,发现即使 session 存储中的元素未定义,它仍然会进入 checkPlaylistName() 方法中的 if block 。渲染语句中的控制台日志运行两次,第一次,它传递一个空数组,这就是我在没有传递元素时想要的,第二次,它由于某种原因传递未定义。这就是导致不同组件出现错误的原因,表示它传递的是未定义的。如果您需要整个存储库,您可以找到它 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;

最佳答案

setState 函数是异步的 ( https://medium.com/@baphemot/understanding-reactjs-setstate-a4640451865b ),因此您将在 checkTracks 方法中返回旧状态。

解决方案: 不要在 checkTracks 方法中设置 State,而是这样:

if (sessionStorage.getItem("playlistTracks") !== undefined) {
    return sessionStorage.getItem("playlistTracks");
}
return [];

并在构造函数中使用此方法来定义状态。

此外,您还可以在渲染函数中设置状态(通过 checkTracks 方法),这会导致无限循环。

关于javascript - 在本地保存和重新加载值的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48955934/

相关文章:

javascript - 恢复div的css属性

reactjs - React Native S3 图片上传使用 XHR 返回 "Stream Closed"

jquery单选按钮冲突

javascript - 使用 JSON 将行传送到 JavaScript

javascript - 动态更改 jquery UI 对话框的大小

javascript - 导入获取请求?

class - 当 setState 与类的对象实例发生 react 时会发生什么

javascript - 以编程方式模拟存储事件

javascript - HTML DOM getElementById()-Node JS

javascript - Lightbox jQuery 插件可以在 HTML 电子邮件中运行吗?