Réagir - Mettre à jour l'état dans le composant de classe en fonction du texte saisi par l'utilisateur après un clic sur le bouton


Nick Kinlen

Je suis relativement nouveau dans React et je crée une application de recette de style liste de tâches. L'utilisateur doit pouvoir ajouter une nouvelle recette, supprimer une recette existante ou modifier une recette existante. J'ai des difficultés à écrire une fonction qui permet à l'utilisateur de cliquer sur le bouton Modifier, puis de soumettre un nouveau titre de recette et / ou de nouveaux ingrédients à cet élément de recette.

Voici le projet . Comment puis-je faire en sorte qu'après avoir cliqué sur l'un des boutons d'édition et soumis le formulaire, le titre de la recette / les ingrédients de cet élément de recette sont mis à jour pour afficher tout ce que l'utilisateur a soumis? J'ai une fonction appelée onSubmitdans mon fichier App.js qui gère les nouveaux éléments de recette créés par l'utilisateur et les ajoute à la liste. J'essaie maintenant d'implémenter une fonction similaire appelée onEditSubmitqui permet à l'utilisateur de mettre à jour les éléments de recette existants mais je suis bloqué.

Voici mon App.js où vit l'État:

 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>
    );
  }

}


Et voici mon conteneur de fonctions Item.js pour les données. Ce conteneur fonctionne très bien lorsqu'il l' onSubmitutilise pour ajouter une nouvelle recette. Mais quand onEditSubmittente de l' utiliser , je reçois une erreur, 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;

À peu près sûr que je fais une erreur Noob React, mais je ne suis pas sûr du problème.

Modifié pour corriger l'erreur de syntaxe dans la fonction onSubmitError: inputVal a changé en inputValEdit, ingrédientVal changé en ingrédientValEdit

Voici les composants fonctionnels pour 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;

Et voici le composant fonctionnel pour 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;
chambre
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
  });
}

vous définissez le itemschamp d'état sur une chaîne. Vous devriez le changer en quelque chose comme:

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

editingIndexvous pouvez stocker dans votre editfonction:setState({editingIndex: index}

Articles connexes