2016-11-29 100 views
0

我從來沒有真正使用localStorage,但似乎很容易。唉,我遇到了一些使用React的奇怪問題。React和localStorage獲得NaN

我試圖在localStorage中保存一個項目的點擊次數,所以當我瀏覽應用程序時它會保存數據。

我一個查看控制檯中的localStorage和setItem作品點擊次數和增量像預期,但一對夫婦的事情發生

  1. 在第一次點擊的點擊次數從DOM消失。
  2. 第一次單擊後,該值變爲NaN
  3. 當我導航到另一個頁面並使用瀏覽器導航返回到該頁面時。信息消失了。我猜這有些事情要做w /一個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; 

回答

1

的問題是在這裏:

this.setState({ 
    clicks: JSON.stringify(localStorage.setItem('link-' + this.props.link, clicks + 1)) 
}); 

localStorage.setItem返回undefined。所以你打破了你的狀態,這就是你有一個空的點擊數的原因。

將方法componentWillMount重命名爲getClicksCount,並在新的componentWillMount和方法​​的末尾調用它。所以這將是更簡單的方法與單一職責:​​只是更新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; 
+0

謝謝。好吧,這是有道理的。它也堅持跨導航,這是好的,但計數器不會增加。另外,數據不會在localStorage中顯示。如果我不使用set數據應該如何進入localStorage? – maxwellgover

+0

當然,你應該使用'localStorage.setItem'來存儲它。我的意思是說你不需要使用它的返回值,而是更好地將它轉換爲單獨的方法。我現在編輯我的答案並嘗試在代碼中顯示我的意思。 –