在我的React应用程序中实现localStorage

时间:2017-03-10 09:22:36

标签: html5 reactjs local-storage

我目前正在进行freeCodeCamp React挑战Building a Recipe Box。 我必须完成使用HTML5 Web存储的用户故事来保存用户所做的更改,这样即使刷新页面,更改仍然存在。但是,我事先没有计划建立my React Application,现在我陷入了一种我不知道如何将此功能添加到我的应用中的情况。

P.S我尝试使用全局变量并设置状态以及设置本地存储。我是React的新手。



/*-------------------------------------------------------------------------*/
var RecipeEdit = React.createClass({
  getInitialState: function() {
    return {
      titleOne: 'Sakkarai Pongal Recipe (Sweet Pongal Recipe)',
      urlOne: 'https://4.bp.blogspot.com/-a1NWFkB9xLU/U1Er4eD_vlI/AAAAAAAAd-w/tUECZ8OUCKw/s1600/sakkarai+pongal+recipe.jpg',
      contentOne: 'Ingredients: Raw rice - 1 cup,Mung bean - 2 to 4 tbsp,Jaggery - 1 cup,Clarified butter - 1/4 cup (can adjust as per preference),Cardamom - 1,Water for cooking rice - 6 cups,Milk - 2 tbsp,Water for jaggery syrup - 1/2 cup,Edible camphor - mustard seed size,Clove - 1,Nutmeg powder- a pinch ,Salt - a pinch (optional),Cashews, raisins - 1 tbsp each',

      titleTwo: 'Medhu Vadai / Ulundu Vadai Recipe',
      urlTwo: 'https://3.bp.blogspot.com/-7qyx9n0Wyxo/UKC3ECH8QGI/AAAAAAAAbs4/WN-0u5cVUxU/s1600/Ulundhu-vadai--Medhu-vadai.jpg',
      contentTwo: 'Ingredients: Black lentil - 3/4 cup,Small onion, shallots(or Big onion – 1) - 10 ,Green pimento pepper - 2 ,Ginger - 1 inch piece,Coriander leaves - 2 tblp, chopped.,Curry leaves - A sprig,Asafoetida - 3-4 pinches,Salt - As needed,Water - As needed',

      titleThree: 'Neer Mor (Recipe For Spiced Buttermilk)',
      urlThree: 'http://farm9.staticflickr.com/8244/8638427263_fc66ac04a3_z.jpg',
      contentThree: 'Ingredients: Plain yogurt - 1 cup,Water - 4 cups,Green pimento pepper - 2,Chopped ginger - 1 tblsp,Chopped cilantro - 1 tblsp,Chopped curry leaves - 1 sprig,Salt - As needed,Asafoetida - 1 pinch,Lemon(optional) - 1/2'
    };
    //localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

 /* componentWillMount: function() {
    var PreviousData = JSON.parse(localStorage.getItem('Furball_Default'));
    if (PreviousData) {
      this.setState({
        [this.state]: PreviousData
      });
    }
  },*/

  handleTitle1Change: function(event) {
    this.setState({
      titleOne: event.target.value
    });
   // localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleTitle2Change: function(event) {
    this.setState({
      titleTwo: event.target.value
    });
   // localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleTitle3Change: function(event) {
    this.setState({
      titleThree: event.target.value
    });
   // localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleUrl1Change: function(event) {
    this.setState({
      urlOne: event.target.value
    });
    //localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleUrl2Change: function(event) {
    this.setState({
      urlTwo: event.target.value
    })
  },

  handleUrl3Change: function(event) {
    this.setState({
      urlThree: event.target.value
    });
    //localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleContent1Change: function(event) {
    this.setState({
      contentOne: event.target.value
    });
   // localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleContent2Change: function(event) {
    this.setState({
      contentTwo: event.target.value
    });
   // localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  handleContent3Change: function(event) {
    this.setState({
      contentThree: event.target.value
    });
    //localStorage.setItem('Furball_Default', //JSON.stringify(this.state));
  },

  render: function() {
    return (<section> 
              <div className="card small horizontal pink lighten-4 z-depth-4">
               <div className="card-image waves-effect waves-block waves-light">
                <img className="activator" src={this.state.urlOne} /> 
    </div>
      
    <div className="card-content">
      <span className="card-title activator grey-text text-darken-4">{this.state.titleOne}</span>
    </div><a className="waves-effect waves-light btn red z-depth-5 del">Delete &nbsp;<span className="fa fa-trash-o fa-lg"> </span></a>
    <div className="card-reveal">
      <span className="card-title"><i className="material-icons right">close</i></span> <div className="input-field inline">
          <input type="text" onChange={this.handleTitle1Change} value={this.state.titleOne} /> 
          <label htmlFor="title">Title</label>
        </div> &nbsp; <div className="input-field inline">
          <input type="text" onChange={this.handleUrl1Change} value={this.state.urlOne} /> 
          <label htmlFor="url">Image URL</label>
        </div><div className="input-field">
      <textarea type="text" className="materialize-textarea" onChange={this.handleContent1Change} value={this.state.contentOne} /> <label>Ingredients/Directions </label> </div>
    </div>
      </div> 
     <div className="card small horizontal brown lighten- z-depth-4">
    <div className="card-image waves-effect waves-block waves-light">
      <img className="activator" src={this.state.urlTwo} /> 
    </div>  
    <div className="card-content">
      <span className="card-title activator grey-text text-darken-4">{this.state.titleTwo}</span>
    </div>
       <a className="waves-effect waves-light btn red z-depth-5 del">Delete &nbsp;<span className="fa fa-trash-o fa-lg"> </span></a>
    <div className="card-reveal">
      <span className="card-title"><i className="material-icons right">close</i></span> <div className="input-field inline">
          <input type="text" onChange={this.handleTitle2Change} value={this.state.titleTwo} /> 
          <label htmlFor="title">Title</label>
        </div> &nbsp; <div className="input-field inline">
          <input type="text" onChange={this.handleUrl2Change} value={this.state.urlTwo} /> 
          <label htmlFor="url">Image URL</label>
        </div><div className="input-field">
      <textarea onChange={this.handleContent2Change} type="text" className="materialize-textarea" value={this.state.contentTwo} /> <label>Ingredients/Directions </label> </div>
    </div>
      </div>  
       
  <div className="card small horizontal lime z-depth-4">
    <div className="card-image waves-effect waves-block waves-light">
      <img className="activator" src={this.state.urlThree} /> 
    </div>  
    <div className="card-content">
      <span className="card-title activator grey-text text-darken-4">{this.state.titleThree}</span>
    </div><a className="waves-effect waves-light btn red z-depth-5 del">Delete &nbsp;<span className="fa fa-trash-o fa-lg"> </span></a>
    <div className="card-reveal">
      <span className="card-title"><i className="material-icons right">close</i></span> <div className="input-field inline">
          <input type="text" onChange={this.handleTitle3Change} value={this.state.titleThree} /> 
          <label htmlFor="title">Title</label>
        </div> &nbsp; <div className="input-field inline">
          <input type="text" onChange={this.handleUrl3Change} value={this.state.urlThree} /> 
          <label htmlFor="url">Image URL</label>
        </div><div className="input-field">
      <textarea onChange={this.handleContent3Change} type="text" className="materialize-textarea" value={this.state.contentThree} /> <label>Ingredients/Directions </label> </div>
    </div>
      </div>  <Form />      
      </section>);
  }
});
/*-------------------------------------------------------------------------*/

var Form = React.createClass({
  getInitialState: function() {
    return {
      title: '',
      url: '',
      content: '',
      clicked: false,
      newCardArr: []
    };
  },

  updateT: function(val) {
    this.setState({
      title: val.target.value
    });
    console.log(this.state.title);
   // localStorage.setItem('Furball_New', //JSON.stringify(this.state));
  },

  updateU: function(val) {
    this.setState({
      url: val.target.value
    });
    console.log(this.state.url);
    //localStorage.setItem('Furball_New', //JSON.stringify(this.state));
  },

  updateC: function(val) {
    this.setState({
      content: val.target.value
    });
    console.log(this.state.content);
   // localStorage.setItem('Furball_New', //JSON.stringify(this.state));
  },

  onClick: function() {
    this.setState({
      clicked: true,
      newCardArr: [<Create key={Math.random()} title={this.state.title} url={this.state.url} content={this.state.content} />, ...this.state.newCardArr]
    });
  },

  render: function() {
    return (<div>  {this.state.clicked ? this.state.newCardArr : null}
      <div className="center-align">
                <ul className="collapsible" data-collapsible="accordion">
    <li> 
      <div className="collapsible-header btn-floating btn-large waves-effect waves-light red z-depth-5"><i className="material-icons">edit</i> </div><h6>Add New Recipe </h6> 
      <div className="collapsible-body"><span><div className="input-field inline">
          <input id="title" type="text" onChange={this.updateT}/> 
          <label className="cyan-text" htmlFor="title">Title</label>
        </div> &nbsp; <div className="input-field inline">
          <input type="text" onChange={this.updateU} /> 
          <label className="cyan-text" htmlFor="url">Image URL</label>
        </div><div className="input-field">
      <textarea type="text" className="materialize-textarea" onChange={this.updateC} /> <label className="cyan-text">Ingredients/Directions </label> </div><button className="btn waves-effect waves-light z-depth-5" onClick={this.onClick} type="submit" name="action">Submit
    <i className="material-icons right">send</i>
  </button> </span></div>
    </li>
    </ul> </div> </div>)

  }
});
/*-------------------------------------------------------------------------*/

var Create = React.createClass({
  getInitialState: function() {
    return {
      title: '',
      url: '',
      content: ''
    };
  },

  componentWillMount: function() {
    this.setState({
      title: this.props.title,
      url: this.props.url,
      content: this.props.content
    });
   /* var PreviousData = JSON.parse(localStorage.getItem('Furball_New'));
    if (PreviousData) {
      this.setState({
        [this.state]: PreviousData
      });
    }*/
  },

  onChange: function(event) {
    this.setState({
      [event.target.id]: event.target.value
    });
   // localStorage.setItem('Furball_New', //JSON.stringify(this.state));
  },

  render: function() {
    console.log(this.state);
    return (<div className="card small horizontal z-depth-4"><div className="card-image waves-effect waves-block waves-light">
      <img className="activator" src={this.state.url} /> 
    </div> <div className="card-content">
      <span className="card-title activator grey-text text-darken-4">{this.state.title}</span>
    </div><a className="waves-effect waves-light btn red z-depth-5 del">Delete &nbsp;<span className="fa fa-trash-o fa-lg"> </span></a><div className="card-reveal">
      <span className="card-title"><i className="material-icons right">close</i></span> <div className="input-field inline">
          <input type="text" id="title" value={this.state.title} onChange={this.onChange} /> 
          <label htmlFor="title">Title</label>
        </div> &nbsp; <div className="input-field inline">
          <input type="text" id="url" onChange={this.onChange} value={this.state.url} /> 
          <label htmlFor="url">Image URL</label>
        </div><div className="input-field">
      <textarea type="text" className="materialize-textarea" id="content" onChange={this.onChange} value={this.state.content} /> <label>Ingredients/Directions </label> </div>
    </div></div>);

  }
});
/*-------------------------------------------------------------------------*/

ReactDOM.render(<RecipeEdit />, document.getElementById('app'));
/*-------------------------------------------------------------------------*/
// var recipes = [];
/*componentWillMount: function() {
    var PreviousData = JSON.parse(localStorage.getItem('Furball_RecipesBox'));
    if (PreviousData) {
      this.setState({
        [this.state]: PreviousData
      });
    }
  },
  
  componentDidUpdate: function(prevProps, prevState) {
    localStorage.setItem('Furball_RecipesBox', JSON.stringify(this.state));
  },*/
/* <div>var recipes = []; array={recipes}
            <Button onClick={this.handleClick} />
        var array= [this.props.array];
    array.push(this.state);     
          </div>*/
// setTimeout(this.after, 5000);
// setTimeout( this.setState({
//   clicked: true
//  }),6000)
//e.preventDefault();
//console.log(this.props.array);
/* componentWillMount: function() {
    var PreviousData = JSON.parse(localStorage.getItem('Furball_RecipesBox'));
    if (PreviousData) {
      this.setState({
        [this.state]: PreviousData
      });
    }
  },

  componentWillUnmount: function() {
    this.setState({
      [this.props.array]: this.state
    });
    console.log(this.props.array);
    localStorage.setItem('Furball_RecipesBox', JSON.stringify(this.props.array)); 
  }, */
&#13;
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-image: url("http://cdn.backgroundhost.com/backgrounds/subtlepatterns/retina_wood.png");
}

#app {
  margin: 15px;
}

.card {
  border-radius: 7%;
}

.del {
  margin-right: 15px;
  margin-top: 10px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/js/materialize.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"> </div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

我认为您的代码的主要问题是假设您在调用this.state后可以立即访问this.setState并且它将包含更新的值。

情况并非如此,这里是why

  

setState()不会立即改变this.state但会创建一个   待定状态转换。调用后访问this.state   方法可以返回现有值。

因此我建议你使用第二个参数并将状态保存到其中的localstorage中,如下所示:

this.setState({
    titleOne: event.target.value,
  },
  () =>
  {
    localStorage.setItem('Furball_Default', JSON.stringify(this.state));
});