【问题标题】:Issue with Saving and Reloading a Value Locally在本地保存和重新加载值的问题
【发布时间】:2018-02-25 04:35:53
【问题描述】:

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

【问题讨论】:

标签: javascript reactjs session-storage


【解决方案1】:

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

解决方案: 不要在你的 checkTracks 方法中设置状态,让它:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-01
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多