Marko
Marko

Reputation: 21

Uncaught TypeError: Cannot read property 'propTypes' of undefined React

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

Answers (1)

Debabrata Mohanta
Debabrata Mohanta

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

Related Questions