Reputation: 21
I am doing this example in Codepen. https://codepen.io/mpance/pen/bpjmdY
Uncaught TypeError: Cannot read property 'propTypes' of undefined: VM198513 react-bootstrap.min.js:13
Also, not sure what it means with the bind warning:
Warning: bind(): You are binding a component method to the component. React does this for you automatically in a high-performance way, so you can safely remove this call. See MainLayout, See RecipesContainer
This code was working fine until I tried implementing the map function in the Recipes component to iterate over the recipes property in state. Then everything took a nose-dive! Do you see anything wrong with this code that I'm missing?
var MainLayout = React.createClass({
getInitialState: function() {
return { recipes: [{recipe: "Pumpkin Pie", ingredients: ["Pumpkin Puree",
"Sweetened Condensed Milk", "Eggs", "Pumpkin Pie Spice",
"Pie Crust"]}],
recipeInput: '',
ingredientsInput: '',
}
},
addRecipe: function() {
var stateCopy = Object.assign({}, this.state);
var recipe = stateCopy.recipes.find(function(elem, idx){
return elem.recipe === this.state.recipeInput;
}.bind(this))
if(recipe === undefined) {
stateCopy.recipes.push({ recipe: this.state.recipeInput, ingredients: this.state.ingredientsInput })
this.setState(stateCopy)
console.log(this.state);
} else {
recipe.ingredients = this.state.ingredientsInput.split(', ');
this.setState(stateCopy);
}
stateCopy.recipeInput = '';
stateCopy.ingredientsInput = '';
},
editRecipe: function(title) {
window.scrollTo(0,0);
document.getElementById('text-area').focus()
var recipe = this.state.recipes.find(function(elem, idx){
return elem.recipe === title;
}.bind(this))
this.setState({ recipeInput: recipe.recipe, ingredientsInput: recipe.ingredients.join(', ')})
},
handleRecipe: function(event) {
this.setState({recipeInput: event.target.value});
},
handleIngredients: function(event) {
this.setState({ingredientsInput: event.target.value});
},
render: function() {
return (
<div className="MainLayout">
<br />
<form id="form">
<h4>Recipe</h4>
<input id="recipe-input" type="text" value={this.state.recipeInput} onChange = {this.handleRecipe} placeholder="Apple Pie" />
<br />
<h4>Ingredients</h4>1
<textarea id="text-area" value={this.state.ingredientsInput} rows="5" cols="50" type="text" onChange = {this.handleIngredients} placeholder="Sugar, milk, etc.">
</textarea>
<br/>
<button className="btn btn-primary" onClick = {this.addRecipe.bind(this)} bsStyle="primary">Add recipe</button>
</form>
{this.state.recipeInput}
<br/>
<br/>
<RecipesContainer editRecipe={this.editRecipe} recipes={this.state.recipes}/>
</div>
)
}
})
var RecipesContainer = React.createClass({
createPanels: function() {
return 1
},
editRecipe: function(title) {
this.props.editRecipe(title);
},
render: function() {
return (<Recipes editRecipe={this.editRecipe.bind(this)} recipes={this.props.recipes}/> )
}
})
var Recipes = React.createClass({
render: function() {
var panels = this.props.recipes.map(function(current, idx) {
(<div>
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title">{current.recipe}</h3>
</div>
<div className="panel-body">
<p>{current.ingredients.join(', ')}</p>
</div>
<button type="button" className="btn btn-primary">Delete</button>
<button type="button" onClick={this.props.editRecipe.bind(null, current.recipe)} className="btn btn-primary">Edit</button>{' '}
</div>
</div>)
}.bind(this))
return panels
}
})
ReactDOM.render(<MainLayout/>, document.getElementById('container'))
Upvotes: 0
Views: 2690
Reputation: 645
Make the following changes in RecipesContainer component
editRecipe={this.editRecipe.bind(this)} to editRecipe={this.editRecipe}.
Similary in MainLayout change
onClick = {this.addRecipe.bind(this)} to onClick = {this.addRecipe}
No need to bind this ,this is automatically passed in React. Modified your pen accordingly : https://codepen.io/Debabrata89/pen/NNLxQv?editors=1111
Upvotes: 1