我有一个应用-待办事项列表,其中包含存储列表项,评论,评论数等不同项目的评论。
您能帮我将localStorage添加到我的应用中,以便将所有项目保存到localStorage吗?
我读过一篇文章,说我们需要设置2个变量的路径:键和对象。我该如何传递所有物品的整个状态?
这是代码:
App.js
import React, { Component } from 'react';
import './App.css';
import ListInput from './components/listInput'
import ListItem from './components/listItem'
import SideBar from './components/sideBar'
import CommentsSection from './components/commentsSection'
class App extends Component {
constructor(props){
super(props);
this.state = {
items: [
{
id: 1,
title: 'First item',
commentsCount: 0,
comments: [],
displayComment: false
},
{
id: 2,
title: 'Second item',
commentsCount: 0,
comments: [],
displayComment: false
},
{
id: 3,
title: 'Third item',
commentsCount: 0,
comments: [],
displayComment: false
},
],
activeItem: {},
isHidden: true
}
}
// Add new item to the list
addItem = inputText => {
let itemsCopy = this.state.items.slice();
itemsCopy.push({id: this.state.items.length + 1, title: inputText, commentsCount: 0, comments: [], displayComment: false});
this.setState({
items: itemsCopy,
})
}
// Remove the item from the list: check if the clicked button id is match
removeItem = id =>
this.setState({
items: this.state.items.filter((item, index) => item.id !== id)
})
addComment = (inputComment) => {
// find item with id passed and select its comments array
const commentCopy = this.state.items.map(item => {
if (item.id === this.state.activeItem.id) {
return {
...item,
commentsCount: item.comments.length + 1,
comments: item.comments.concat({id: item.comments.length + 1, text: inputComment})
}
}
return item
});
this.setState({
items: commentCopy
})
}
getActiveItem = () => this.state.items.find(item => item.id === this.state.activeItem.id)
render() {
console.log(this.state.items.isHidden)
return (
<div className='App'>
<SideBar />
<div className='flex-container'>
<div className='list-wrapper'>
<h1>Items</h1>
<ListInput inputText='' addItem={this.addItem}/>
<ul>
{
this.state.items.map((item) =>
(<ListItem
item={item}
key={item.id}
id={item.id}
removeItem={this.removeItem}
setActiveComment={() => this.setState({ activeItem: item })}
toggleHidden={() => this.setState({ isHidden: false })}
/>
))
}
</ul>
</div>
<div>
{!this.state.isHidden && <CommentsSection
addComment={this.addComment}
activeItem={this.getActiveItem()}
/>}
</div>
</div>
</div>
);
}
}
export default App;
commentSection.js
import React from 'react';
import CommentInput from './commentInput'
import CommentsItem from './commentsItem'
import './commentsSection.css';
export default class CommentsSection extends React.Component {
constructor(props){
super(props);
this.state = {value: ''};
}
handleChange = event => this.setState({value: event.target.value})
handleEnter = event => {
if (event.charCode === 13 && event.ctrlKey) {
console.log(this.state, this.props)
this.addComment(this.state.value)
}
}
addComment = comment => {
console.log(this.props.activeComment)
// Ensure the comment text isn't empty
if (comment.length > 0) {
this.props.addComment(comment);
this.setState({value: ''});
}
}
render() {
return (
<div className='component-section'>
<h1>{this.props.activeItem && this.props.activeItem.title}</h1>
<ul>
{ this.props.activeItem &&
this.props.activeItem.comments.map((comment) => <p key={comment.id}>{comment.text}</p>)
}
</ul>
{/*<CommentsItem />*/}
{/*<CommentInput addComment={this.addComment}/>*/}
<div className='comment-input'>
<input type='text' value={this.state.value} onChange={this.handleChange} onKeyPress={this.handleEnter}/>
</div>
</div>
)
}
}
listInput.js
import React from 'react';
import './listInput.css'
export default class ListInput extends React.Component {
constructor(props){
super(props);
this.state = {value: this.props.inputText};
this.handleChange = this.handleChange.bind(this);
this.addItem = this.addItem.bind(this);
}
handleChange = event => this.setState({value: event.target.value})
addItem(item) {
// Ensure the todo text isn't empty
if (item.length > 0) {
this.props.addItem(item);
this.setState({value: ''});
}
}
render() {
return (
<div className='list-input'>
<input type='text' value={this.state.value} onChange={this.handleChange} placeholder={'Type name here...'}/>
<button className='btn btn-primary' onClick={() => this.addItem(this.state.value)}>Add new</button>
</div>
)
}
}
答案 0 :(得分:1)
反应非常容易。
// setter
localStorage.setItem('myData', data);
// getter
localStorage.getItem('myData');
您可以通过浏览器自动访问localStorage
对象。请记住,.setItem
没有返回值,因此请同步使用它。
答案 1 :(得分:1)
localStorage有两种重要方法:
localStorage.setItem(*name*,*string value*)
name
只是您希望存储在Storage中以轻松引用数据的键。string value
只是您希望存储在key/name
下的“存储”中的值。重要的是它必须是一个字符串。 localStorage
无法存储数组和/或对象 localStorage.getItem(*name*)
name
,它是先前为name
设置的setItem
。 key/name
中不存在localStorage
,则返回空;如果存在 ,则返回字符串值。为什么这些事情很重要?状态是一个对象。让我们创建一个小版本:
let state = { name: "zak" };
如前所述,您不能在localStorage
中存储除 string 以外的任何内容。那我们该怎么办呢?我们要存储状态,对不对?嗯...我们必须将对象转换为一个字符串。
我们可以使用JSON
方法来做到这一点:
JSON.stringify(**object or array**)
JSON.parse(**string**)
我们有一个状态 Object ,我们需要将其转换为 string ,然后才能使用localStorage.setItem
保存它。为此,我们使用JSON.stringify
。
使用localStorage.getItem
时,我们将以字符串的形式接收状态对象的表示,我们需要先将其转换为状态 object 在我们的应用程序中使用它。为此,我们使用JSON.parse
。
保存的代码示例:
let state = { name: "zak" };
let state_string = JSON.stringify(state);
localStorage.setItem("my_saved_state", state_string);
以上内容将处于状态,将其转换为字符串并保存。要进行相反的操作,我们只需获取字符串,然后将其变回对象。
LOADING的代码示例:
let state = { name: "zak" };
let state_string = JSON.stringify(state);
localStorage.setItem("my_saved_state", state_string);
let returned_state_string = localStorage.getItem("my_saved_state");
let returned_state_object = JSON.parse(returned_state_string);
以上结果为:
console.log(returned_state_object); // { name: "zak" }
console.log(state); // { name: "zak" }
如您所见,您已经有效地保存和加载了localStorage
。
使用setItem
API的getItem
和localStorage
方法。
然后可以通过name
使用JSON.stringify
和字符串对象进行保存。这很重要,因为storage api
仅 允许保存字符串。 没有对象文字,没有数组等。
然后可以通过引用name
并通过JSON.parse
解析返回的String来加载。这将有效地将字符串重新水化为原始的对象/数组形式。
重要说明:存储在state
中的对象或数组中的所有引用在转换为字符串时都会中断。显然,字符串不能作为引用,所以这很有意义。为了解决这个问题,您可以创建一个解析器来重新设计引用,但这超出了此答案的范围。
我会承认一点意见,但是我认为这是一个广为人知的意见,那就是在使用Storage API时最好使用函数,因为它可以使编码更加清晰。下面是一个保存状态,加载状态并测试保存状态和加载状态是否相同以证明其概念的示例。
重要说明:您会注意到,在加载函数中,我们首先在raw_data
中接收数据-这是因为如果密钥不存在(即第一个运行该程序时,您将不会保存数据),它将返回null
。这是一个简单的健全性检查,如果不存在空对象,它将返回一个空对象-在您的情况下,您可能想抛出一个错误,但这取决于您。
StackOverflow不允许使用存储,它会出现,因此,如果您想查看运行的版本,请查看此随附的fiddle
let state = {
items: [{
id: 1,
title: 'First item',
commentsCount: 0,
comments: [],
displayComment: false
},
{
id: 2,
title: 'Second item',
commentsCount: 0,
comments: [],
displayComment: false
},
{
id: 3,
title: 'Third item',
commentsCount: 0,
comments: [],
displayComment: false
},
],
activeItem: {},
isHidden: true
}
function saveAs(name, state_obj) {
let data = JSON.stringify(state_obj);
localStorage.setItem(name, data);
console.log("saved!");
}
function loadFrom(name) {
let raw_data, data;
raw_data = localStorage.getItem(name);
if (!raw_data) return {};
data = JSON.parse(raw_data);
return data;
}
function test(_old, _new) {
return JSON.stringify(_old) === JSON.stringify(_new);
}
saveAs("my_saved_state", state);
let myNewState = loadFrom("my_saved_state");
console.log( test(state, myNewState) ? "old and new are the same!" : "old and new are different" );