Reputation: 323
class App extends Component {
constructor(props){
super(props);
this.state={ recipes :{} }
this.addRecipe=this.addRecipe.bind(this);
}
addRecipe (recipe) {//add new fish to recipes
var timestamp = (new Date()).getTime();
this.state.recipes['recipe'+timestamp] = recipe;
this.setState({ recipes : this.state.recipes });
}
componentWillMount(){
this.setState({
recipes : require('./sample-recipes')
});
}
render() {
return (
<div className="App">
<h2>Welcome to the Recipe Book</h2>
<button> {/*onClick, how to call Addrecipe here.*/ }
Add Recipe
</button>
<AddRecipe addRecipe={this.addRecipe}/>
<div>{this.state.recipes}</div>
</div>
);
}
}
var AddRecipe = React.createClass({
create : function(event) {
event.preventDefault();
var recipe = {
name : this.refs.name.value,
ingredients:this.refs.ingredients.value
}
this.props.addRecipe(recipe);
this.refs.form.reset();
},
render : function() {
return (
<form className="add" ref="form" onSubmit={this.create}>
<span> Recipe <input type="text" ref="name" placeholder="Recipe Name"/>
</span>
<span>Ingredients <input type="text" ref="ingredients"
placeholder="ingredients" /></span>
<button type="submit">Add</button>
<button type="submit">Cancel</button>
</form>
)
}
});
export default App;
I am building this recipe book in reactjs (i have started learning react).
1) How do I display all the recipes from file sample-recipes.js on page load. Why it doesn't display all the recipes in the file on writing {this.state.recipes}.
2) How should I call AddRecipe component on click of the button (Add Recipe).
Upvotes: 1
Views: 180
Reputation: 226
1) Recipes should be an array which you have to map and return html or another component for every object inside. First you have to change current state structure to something like this:
componentWillMount(){
this.setState({
recipes : [{
//include timestamp here, I created example recipe to get it to work
name : 'Tomato',
ingredients:'Just Tomato'
}]
});
}
Then in addRecipe function you have to add next recipe to an array and you CAN NOT use this.state.sth outside constructor:
addRecipe (recipe) {
this.setState({ recipes: [...this.state.recipes, recipe]});
}
Of course, you can map an object as you tried, but it's easier to work with arrays.
Now you can display recipes this way:
<ul>
{this.state.recipes.map(recipe => {
return <li>{recipe.name}</li>
})}
</ul>
2) You need another state variable, something like displayAddRecipeForm. Then bind a function which changes the state to the opposite:
<button onClick={() => {this.setState({ displayAddRecipeForm: !this.state.displayAddRecipeForm })}}>Add Recipe</button>
Pass the state to AddRecipe component as a property and set the className basing on props:
<form className={this.props.display ? '' : 'hide'} ref="form" onSubmit={this.create}>
Upvotes: 1