React - 根据用户在单击按钮后输入的文本更新 class 组件中的状态

React - Update state in class component based on text inputted by user after button click

我对 React 和创建待办事项列表样式 Recipe 应用比较陌生。用户应该能够添加新食谱、删除现有食谱或编辑现有食谱。我在编写允许用户单击编辑按钮然后向该食谱项提交新食谱标题 and/or 新成分的函数时遇到问题。

Here is the project。单击其中一个编辑按钮并提交表单后,如何更新该食谱项的食谱 title/ingredients 以显示用户提交的内容?我的 App.js 文件中有一个名为 onSubmit 的函数,用于处理用户创建的新食谱项目并将它们添加到列表中。我现在正在尝试实现一个名为 onEditSubmit 的类似功能,它允许用户更新现有的食谱项目,但我被卡住了。

这是我的 App.js 所在州所在的地方:

 export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: ["Pumpkin Pie", "Spaghetti", "Onion Pie"],
      ingredients:[
        ["Pumpkin Puree ", "Sweetened Condensed Milk ", "Eggs ", "Pumpkin Pie Spice ", "Pie Crust "],
        ["Noodles ", "Tomato Sauce ", "(Optional) Meatballs "],
        ["Onion ", "Pie Crust "]
      ],

      // Recipe name and ingredients
      inputVal: '',
      ingredientVal: '',
      // Recipe name and ingredients when user is editing existing recipe
      inputValEdit: '',
      ingredientValEdit: '',
      // Controls whether forms are displayed or hidden
      showRecipeForm: false,
      showRecipeEditForm: false
    };

  }

  // Get text user inputs for recipes
  handleChange = (event) => {
    this.setState({ [event.target.name]: event.target.value });
  };


  // When user submits recipe this adds it to the list
  onSubmit = (event) => {
    event.preventDefault()
    this.setState({
      items: [...this.state.items, this.state.inputVal],
      ingredients: [...this.state.ingredients, this.state.ingredientVal],
      showRecipeForm: false
    });
  }

  // Should edit and update a recipe item when user clicks edit button and then submits RecipeEditForm, not working
  onEditSubmit = (event) => {
    event.preventDefault()
    // This setState shoul erase previous recipe state and rewrite it with the details the user entered after editing that particular recipe item
    this.setState({
      items: this.state.inputValEdit,
      ingredients: this.state.ingredientValEdit,
      showRecipeEditForm: false
    });
  }

  closeRecipeForm = () => {
    this.setState({
      showRecipeForm: false,
      showRecipeEditForm: false
    });
  }

  // Shows recipe
  AddRecipe = (bool) => {
    this.setState({
      showRecipeForm: bool
    });
  }

  // Is called when one of the edit recipe buttons is clicked, shows RecipeEditForm
  edit = (item, index) => {
    console.log('Edit button clicked');
    console.log('index is ' + index);
    this.setState({ showRecipeEditForm: !this.state.showRecipeEditForm });
  }

  // Deletes recipe item from the list
  delete = (item, index) => {
     this.setState({
      ingredients : this.state.ingredients.filter((_, i) => i !== index),
      items: this.state.items.filter((_, i) => i !== index)
    });
  }


  render() {
    return (
      <div className="Recipe-List">
        <h1>Recipe List</h1>

        <Item
          items={this.state.items}
          ingredients={this.state.ingredients}
          edit={this.edit}
          delete={this.delete}
        />

        <button onClick={this.AddRecipe}>Add New Recipe</button>

        {/* Shows form to edit recipe */}
        { this.state.showRecipeEditForm ?

          <RecipeEditForm
            inputValEdit={this.state.inputValEdit}
            handleChange={this.handleChange}
            ingredientValEdit={this.state.ingredientValEdit}
            onEditSubmit={this.onEditSubmit}
            closeRecipeForm={this.closeRecipeForm}
          />

          :null
        }

        {/* Shows form to add new recipe to the list */}
        { this.state.showRecipeForm ?

          <RecipeForm
            inputVal={this.state.inputVal}
            handleChange={this.handleChange}
            ingredientVal={this.state.ingredientVal}
            onSubmit={this.onSubmit}
            closeRecipeForm={this.closeRecipeForm}
          />

          :null
        }

      </div>
    );
  }

}


这是我的 Item.js 数据函数容器。当 onSubmit 使用它添加新配方时,此容器工作正常。但是当 onEditSubmit 尝试使用它时,我得到一个错误,props.items.map is not a function

import React from 'react';

const Item = (props) => (
  <div>
    <div className="Recipe-Item" key={props.text}>

        {props.items.map((item, index) =>
        <div className="Recipe-Item-Container">
        <ul>
          <li key={index}>
            {item}
          </li>
          <li>
            {props.ingredients[index]}
          </li>
        </ul>

          <button onClick={() => props.edit(item, index)}>Edit</button>
          <button onClick={() => props.delete(item, index)}>Delete</button>

        </div>
      )}
    </div>
  </div>
)


export default Item;

很确定我正在犯一个 noob React 错误,但我不确定问题出在哪里。

已编辑以更正 onSubmitError 函数中的语法错误:inputVal 更改为 inputValEdit,ingredientVal 更改为 ingredientValEdit

以下是 onSubmit 的功能组件:

import React, { Component } from 'react';


const RecipeForm = (props) => {
  return (
    <div>
      <form className="Recipe-Form" onSubmit={props.onSubmit}>
        <p className="x-close" onClick={props.closeRecipeForm}>X</p>
        <div className="form-content">
          <label>Recipe Name</label>

          <input
            name="inputVal"
            value={props.inputVal}
            onChange={props.handleChange}
          />

          <label>Ingredients</label>
          <input
            name="ingredientVal"
            value={props.ingredientVal}
            onChange={props.handleChange}
          />

          <button>Submit</button>
        </div>
      </form>
    </div>
  );
}

export default RecipeForm;

这里是 onEditSubmit 的功能组件:

import React, { Component } from 'react';


const RecipeEditForm = (props) => {
  return (
    <div>
      <form className="Recipe-Form Edit-Form" onSubmit={props.onEditSubmit}>
        <p className="x-close" onClick={props.closeRecipeForm}>X</p>
        <div className="form-content">
          <h1>This is the edit form</h1>

          <label>Edit Recipe</label>
          <input
            name="inputValEdit"
            value={props.inputValEdit}
            onChange={props.handleChange}
          />

          <label>Ingredients</label>
          <input
            name="ingredientValEdit"
            value={props.ingredientValEdit}
            onChange={props.handleChange}
          />

          <button>Submit</button>
        </div>
      </form>
    </div>
  );
}

export default RecipeEditForm;

您需要扩展 <App/> 状态,以便您的应用程序可以跟踪当前正在编辑食谱列表中的哪个食谱项目。

例如,您可以存储用户正在编辑的食谱数据的索引。然后,您将在 onEditSubmit() 函数期间使用此索引更新列表中的正确食谱:

 onEditSubmit = (event) => {
    event.preventDefault()

    // Get the index of the recipe we're currently editing
    const currentlyEditingIndex = this.state.currentlyEditingIndex

    // Clone data arrays for mutation
    const items = [].concat(this.state.items)
    const ingredients = [].concat(this.state.ingredients)

    // Update data arrays
    items[ currentlyEditingIndex ] = this.state.inputValEdit;
    ingredients[ currentlyEditingIndex ] = this.state.ingredientValEdit;

    this.setState({
       items: items,
       ingredients: ingredients,
      showRecipeEditForm: false
    });
  }

为此,您还需要像这样更新 edit 函数:

edit = (item, index) => {
    console.log('Edit button clicked');
    console.log('index is ' + index);
    this.setState({ 

       // Store the index of the recipe being edited
       currentlyEditingIndex : index, 
       showRecipeEditForm: !this.state.showRecipeEditForm 
    });
  }

希望对您有所帮助!

onEditSubmit = (event) => {
  event.preventDefault()
  // This setState shoul erase previous recipe state and rewrite it with the 
  details the user entered after editing that particular recipe item
  this.setState({
    items: this.state.inputVal,
    ingredients: this.state.ingredientVal,
    showRecipeEditForm: false
  });
}

您正在将 items 状态字段设置为字符串。您应该将其更改为:

onEditSubmit = (e) => {
  e.preventDefault();
  const {items, ingredients, inputVal, ingredientVal, editingIndex} = this.state;
  items[editingIndex] = inputVal;
  ingredients[editingIndex] = ingredientVal;
  this.setState({
    items,
    ingredients,
    inputVal: '',
    ingredientVal: ''
  });
}

editingIndex 您可以在 edit 函数中存储的位置:setState({editingIndex: index}