简体   繁体   English

React子组件props:_this2.props.delete不是函数

[英]React child component props : _this2.props.deleteIt is not a function

I'd like your insight with my attempt at creating a Recipe Box. 尝试创建食谱盒时,我希望您的见解。

https://codepen.io/gianndall/pen/evyBYd?editors=0010 https://codepen.io/gianndall/pen/evyBYd?editors=0010

class RecipeList extends React.Component {

  constructor(props) {
    super(props); 
    this.state = {
    }
  }

  render() { 
        var list = JSON.parse(this.props.recipes);
  console.log (list);
    return (      
      <ul className="collection">
        {list.map( (x) => 
                  <li className="collection-item">
                    <div>
                      {x.name} {list.indexOf(x)}                      
                      <a href="#!" className="secondary-content">
                        <i className="material-icons"
                          onClick = {() => this.props.deleteIt(list.indexOf(x))}
                          >delete</i></a>
                      <a href="#!" className="secondary-content"><i className="material-icons">edit</i></a>
                    </div>
                  </li> )}
      </ul>
    )
  }
}

class AddRecipeModal extends React.Component {

    constructor(props) {
    super(props);
    this.state = {
      input1: '',
      textarea1: ''
    }
  }    

  handleChangeTextarea(event) {
    this.setState({textarea1: event.target.value});
  }
  handleChangeInput(event) {
    this.setState({input1: event.target.value});
  }

  handleSubmit(event) {
    alert('A recipe was submitted: ' + this.state.input1 + ' '+ this.state.textarea1);
    event.preventDefault();
     if(typeof(Storage) !== "undefined") {

    console.log(localStorage.Recipes);

    if (localStorage.Recipes){

      var newRecipe = this.state.input1;
      var newIngredient = this.state.textarea1.split(',');
      console.log( 'vers 2' , newRecipe);
      var x = JSON.parse( localStorage.Recipes );
      console.log('vers 2' , x);
      x.push(
        {name:newRecipe,
         contans: newIngredient
        }
      );
      var updated = localStorage
      .setItem('Recipes',JSON.stringify(x));

    }else{
      var i=[];
      var newRecipe = this.state.input1;
      var newIngredient = this.state.textarea1.split(',');
      i.push(
        {name:newRecipe,
         contans: newIngredient
        }
      );
      localStorage
      .setItem('Recipes',JSON.stringify(i));
      console.log('vers 1 i= ',i);
      console.log('vers1 RECIPES ', localStorage.Recipes);      
    }

  }else{
        alert("Sorry, your browser does not support web storage...");
    }
  console.log('test');
    {this.props.closeIt()}
  }

  render() {
    return(

    <div id="modal1" className= {'modal ' + (this.props.display ? 'open' : '') }>
        <div className="modal-content">
          <h4>Add Recipe</h4>
          <form onSubmit={this.handleSubmit.bind(this)} >
          <div className="input-field" >
            <input id="input1" type="text" value={this.state.input1} onChange={this.handleChangeInput.bind(this)} />
            <label for="first_name">Recipe Name</label>
          </div>

          <div className="input-field" >
          <textarea id="textarea1" className="materialize-textarea" value={this.state.textarea1} onChange={this.handleChangeTextarea.bind(this)} />
          <label for="textarea1">Ingredient - separate with comma:</label>
          </div>
            <button type="Submit" className="waves-effect waves-light btn"><i className="material-icons left">add</i>Add it</button>
          </form>
        </div>
        <div className="modal-footer">
          <a href="#!" className="modal-action modal-close waves-effect waves-green btn-flat" onClick={this.props.closeIt}>Cancel</a>
        </div>
      </div>
      )
  }

}

class RecipesBox extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      modalShow: false
    }
  }  

  openModal(){
    this.setState({
      modalShow: true
    })
  }

  closeModal(){
    this.setState({
      modalShow: false
    })
  }

  deleteRecipe(x) {
    console.log('test', x);
    var list = JSON.parse(localStorage.Recipes);
    list.splice(x,1);
    console.log('list =',list);
    localStorage.Recipes = JSON.stringify(list);
  };


  render() {

    const listed = localStorage.Recipes ?
        <RecipeList recipes={localStorage.Recipes} deletIt={this.deleteRecipe}/> :
        <ul className="collection"><li className="collection-item">The Recipe Box is empty</li>
      </ul> 

      return (      
      <div>
        <nav className="nav-extended">
          <div className="nav-content">
            <span className="nav-title">Recipe Box</span>
            <a className="btn-floating btn-large halfway-fab waves-effect waves-light teal" onClick={this.openModal.bind(this)}>
              <i className="material-icons">add</i>
            </a>
          </div>
        </nav>
        {listed}
        < AddRecipeModal display={this.state.modalShow} closeIt ={this.closeModal.bind(this)}/>


   </div>      
    )    
  }
}

class newRecipe extends React.Component {}

ReactDOM.render(
  < RecipesBox />,
  document.getElementById('app')
);

After few days of reading and frustration, I can't delete the list item. 经过几天的阅读和沮丧,我无法删除列表项。 I have a problem creating a props function with arguments that passes a value from child to parent (specifically the local storage array index). 我在创建带有参数的props函数时遇到问题,该函数将值从子级传递到父级(特别是本地存储数组索引)。

I keep getting a _this2.props.deleteIt is not a function error 我不断收到_this2.props.deleteIt is not a function错误

I can, of course, create a massive Component and make my life easier, but that's not the point. 我当然可以创建一个庞大的组件并使我的生活更轻松,但这不是重点。 I want to learn how to handle smaller components 我想学习如何处理较小的组件

I'd really hope you can provide a fresh look on this. 我真的希望您能对此有所了解。

Thank you 谢谢

You have to pass it in as deleteIt , not deletIt : 您必须将其作为deleteIt而不是deletIt

<RecipeList deletIt={this.deleteRecipe} />

should be 应该

<RecipeList deleteIt={this.deleteRecipe} />

Also, in the future you may need to reference this inside of the deleteRecipe method. 另外,将来您可能需要在deleteRecipe方法中引用this方法。 So at that point you may want to use an arrow function or .bind . 因此,此时您可能需要使用箭头功能或.bind

Well, it looks like you mistyped something: 好吧,看来您输入了错误的内容:

<RecipeList recipes={localStorage.Recipes} deletIt={this.deleteRecipe}/> :

Should be like this: 应该是这样的:

<RecipeList recipes={localStorage.Recipes} deleteIt={this.deleteRecipe}/> :

As your component will not trigger a render on deletion, i suggest you 3 options : 由于您的组件不会在删除时触发渲染,因此我建议您3个选择:

  • Store your recipes in your main component state to handle your components rendering. 将配方存储在主要组件状态中以处理组件渲染。
  • Add a localStorage listener in your main component. 在您的主要组件中添加一个localStorage侦听器。
  • Use a store provider (like redux) 使用商店提供商(例如redux)

Edit : Try to avoid forceUpdate(), from official doc : 编辑:尝试避免从官方文档中使用forceUpdate():

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). 通常,您应该避免使用forceUpdate(),而只能从render()中的this.props和this.state中读取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM