2016-11-29 11 views
0

以前はlocalStorageを使ったことはありませんでしたが、それは十分に簡単だったようです。悲しいかな、私はReactでそれを使っていくつかの奇妙な問題にぶち当たっています。ReactとlocalStorageでNaNを取得する

アイテムのクリック数をlocalStorageに保存しようとしているので、アプリをナビゲートするとデータが保存されます。

私は、コンソールでのlocalStorageを表示し、期待されるようなものによるクリックや刻みでsetItem作品が、物事が最初に

  1. を起こっているカップルはクリック数がDOMから消えているをクリックします。
  2. 最初のクリック後、値はNaN
  3. になります。別のページに移動し、ブラウザのナビゲーションを使用してそのページに戻ると、情報はなくなりました。私はこれが何かを持っていると推測しています。リアックフック私は正しく使用していませんが、間違っている可能性があります。

ここにコードがあります。

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)) 
}); 

undefinedを返しますlocalStorage.setItem。だからあなたはあなたの状態を壊し、それが空のクリック番号を持っている理由です。

componentWillMountgetClicksCountに変更し、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'を使ってそれを保存してください。つまり、戻り値を使用して別のメソッドに移動する必要はありません。私は今私の答えを編集し、私がコードで意味することを示すことを試みる。 –

関連する問題