我以前从未真正使用过 localStorage,但它看起来很简单。唉,我在 React 中使用它时遇到了一些奇怪的问题。
我正在尝试保存 localStorage 中某个项目的点击次数,以便当我在应用程序中导航时它会保存数据。
我在控制台中查看了 localStorage,setItem
可以在点击时工作,并按预期增加 1,但发生了一些事情
- 第一次点击时,点击次数将从 DOM 中消失。
- 第一次点击后,值变为
NaN
- 当我导航到另一个页面并使用浏览器导航返回该页面时。信息没了。我猜这与我没有正确使用的 React hook 有关,但我可能是错的。
这是代码。
import React, { Component } from 'react';
import {IndexLink} from 'react-router';
/* eslint-disable */
import Item from '../styles/LinkItem.css';
class LinkItem extends Component {
constructor(props) {
super(props);
this.state = {
clicks: 0,
text: this.props.link,
newText: null
};
}
getClicksCount() {
const localStorageRef = localStorage.getItem('link-' + this.props.link);
if(localStorageRef) {
this.setState({
clicks: JSON.parse(localStorageRef) + 1
})
}
}
componentWillMount() {
this.getClicksCount()
}
editLink() {
const newText = prompt('Update your link');
this.setState({
newText: newText
}, function(){
this.props.data.updateLink(this.props.index, this.state.newText);
})
}
handleClick(e) {
e.preventDefault();
const clicks = this.state.clicks;
this.getClicksCount();
}
render() {
return (
<tr>
<td>
<IndexLink onClick={this.handleClick.bind(this)} to={{pathname: 'landing/' + this.props.link}}>{this.state.newText != null ? this.state.newText : this.props.link}</IndexLink>
</td>
<td>{this.state.clicks}</td>
<td><button className="btn btn-default" onClick={this.editLink.bind(this)}>Edit</button></td>
<td><button className="btn btn-danger" onClick={this.props.data.deleteLink.bind(null, this.props.index)}>Delete</button></td>
</tr>
);
}
}
export default LinkItem;
最佳答案
问题出在这里:
this.setState({
clicks: JSON.stringify(localStorage.setItem('link-' + this.props.link, clicks + 1))
});
localStorage.setItem 返回未定义。所以你打破了你的状态,这就是你点击次数为空的原因。
将方法 componentWillMount
重命名为 getClicksCount
,并在新的 componentWillMount
和方法 handleClick
的末尾调用它>。因此,它将是具有单一职责的更简单的方法:handleClick
仅更新 localStorage,getClicksCount
仅更新状态。
UPD:我写了一些方法和注释。我没有测试过,但我认为这会起作用。欢迎提问。
import React, { Component } from 'react';
import { IndexLink } from 'react-router';
/* eslint-disable */
import Item from '../styles/LinkItem.css';
class LinkItem extends Component {
constructor(props) {
super(props);
this.state = {
clicks: 0,
text: this.props.link,
newText: null
};
}
// new methods:
getStoreKey() {
return 'link-' + this.props.link;
}
getClicksCount() {
const key = this.getStoreKey();
const value = localStorage.getItem(key);
return JSON.parse(value);
}
setClicksCount(newValue) {
const key = this.getStoreKey();
localStorage.setItem(key, newValue);
}
updateClicksCountState(val) {
this.setState({
clicks: val,
});
}
//
componentWillMount() {
this.updateClicksCountState(this.getClicksCount()); // that should update state with value from localStorage
}
editLink() {
const newText = prompt('Update your link');
this.setState({
newText: newText
}, function(){
this.props.data.updateLink(this.props.index, this.state.newText);
})
}
handleClick(e) {
e.preventDefault();
const oldValue = this.getClicksCount();
const newValue = oldValue + 1;
this.setClicksCount(newValue); // that will update value in localStorage
this.updateClicksCountState(newValue); // that will update state -> render component
}
render() {
return (
<tr>
<td>
<IndexLink onClick={this.handleClick.bind(this)} to={{pathname: 'landing/' + this.props.link}}>{this.state.newText != null ? this.state.newText : this.props.link}</IndexLink>
</td>
<td>{this.state.clicks}</td>
<td><button className="btn btn-default" onClick={this.editLink.bind(this)}>Edit</button></td>
<td><button className="btn btn-danger" onClick={this.props.data.deleteLink.bind(null, this.props.index)}>Delete</button></td>
</tr>
);
}
}
export default LinkItem;
关于javascript - React 和 localStorage 获取 NaN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40869053/