我目前正在进行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 <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> <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 <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> <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 <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> <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> <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 <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> <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;
答案 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));
});