javascript - React 和 localStorage 获取 NaN

标签 javascript reactjs local-storage

我以前从未真正使用过 localStorage,但它看起来很简单。唉,我在 React 中使用它时遇到了一些奇怪的问题。

我正在尝试保存 localStorage 中某个项目的点击次数,以便当我在应用程序中导航时它会保存数据。

我在控制台中查看了 localStorage,setItem 可以在点击时工作,并按预期增加 1,但发生了一些事情

  1. 第一次点击时,点击次数将从 DOM 中消失。
  2. 第一次点击后,值变为NaN
  3. 当我导航到另一个页面并使用浏览器导航返回该页面时。信息没了。我猜这与我没有正确使用的 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/

相关文章:

javascript - Ionic + Angular 默认无法勾选ion-radio

javascript - 使用字典将返回的状态映射到选择下拉列表以进行过滤,会产生我试图删除的重复项并将唯一键附加到

reactjs - React-Native是单线程执行还是多线程执行?

spring - 如果远程存储库不可用,如何为 Spring Cloud Config 服务设置本地后备配置?

javascript - 如何在 localStorage 中存储列表

javascript - 在 HighCharts 中隐藏/显示多个系列

javascript - XML 文档可以支持 HTML 表单吗?

javascript - 如何在reactjs组件中在浏览器上呈现JSON列表?

reactjs - Dispatch 覆盖 React Js 中的完整存储

javascript - 对象数组未显示所有变量