我之前从未真正使用过localStorage,但这似乎很容易。唉,我遇到了一些与React一起使用它的奇怪问题。
我试图保存localStorage中项目的点击次数,因此当我浏览应用程序时会保存数据。
我在控制台中查看localStorage,而setItem
可以按照预期的方式点击和增加点击,但有几件事情正在发生
NaN
这是代码。
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;
答案 0 :(得分:1)
问题在于:
this.setState({
clicks: JSON.stringify(localStorage.setItem('link-' + this.props.link, clicks + 1))
});
localStorage.setItem返回undefined。所以你打破了你的状态,这就是为什么你有一个空的点击数字。
将方法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;