Добавление элемента в словарь состояний реакции

#javascript #reactjs

Вопрос:

Я хочу добавить элемент в словарь состояний реакции. Каждый раз, когда я нажимаю кнопку «Отправить», я получаю значение, не определенное для объекта словаря, и оно добавляется в диктонарий с нулевыми значениями в имени и стоимости, но идентификатор работает нормально. Я нахожу проблему, но не могу найти решение. ТИА.

 import React, { Component } from "react";
import ExpenseItem from "./ExpenseItem.js";


class ExpensesList extends Component {
state = {
  expenses: [{id: '12345' ,name: 'Pizza', cost: '20'}],
};

handleChange=(event)=>{
this.setState({[event.target.name]:event.target.value});
}
handleSubmit = (event) => {
  event.preventDefault(); 

  this.setState({expenses: [this.state.expenses,...[{id: Math.random(),name:this.state.expenses.name, cost:this.state.expense.cost}]]});

}

render() {
return (
  <div>
    <ul className="list-group">
    {this.state.expenses.map((expense) => (
      <ExpenseItem
        id={expense.id}
        name={expense.name}
        cost={expense.cost}
      />
    ))}
  </ul>
  <div className ="row mt-3">
  <h2> Add Expenses </h2>
  <form onSubmit={this.handleSubmit}>
    <div className="row">
      <div className="form-group">
        <label for="name">Name</label>
        <input
          required="required"
          type="text"
          className="form-control"
          id="name"
          value = {this.state.expenses.name}
          onChange = {this.handleChange}
        ></input>
      </div>
      <div className="form-group">
        <label for="name">Cost</label>
        <input
          required="required"
          type="text"
          className="form-control"
          id="cost"
          value = {this.state.expenses.cost}
          onChange = {this.handleChange}
        ></input>
      </div>
      <div className="form-group">
        <button type="submit" className="btn btn-primary"> Add Expense</button>
      </div>
    </div>
  </form>
  </div>
  
  </div>
  
  
);
}
}

export default ExpensesList;
 

Комментарии:

1. Вы радикально меняете структуру государства в handleSubmit и в handleChange. Math.random () — плохой способ получить уникальные идентификаторы. Почему вы создаете, а затем распространяете один массив значений?

Ответ №1:

Проблема в том, что this.state.expenses это массив. Итак, this.state.expenses.name и this.state.expenses.cost то, и другое не определено.

Если вы хотите иметь возможность добавлять новые объекты расходов в expenses массив в состоянии, вам нужен способ управления новыми входными данными в состоянии. Итак, ваше состояние должно выглядеть примерно так:

 state = {
  expenses: [{id: '12345' ,name: 'Pizza', cost: '20'}],
  cost: "",
  name: ""
};

 

Когда пользователь вводит стоимость и имя this.state.cost и this.state.name должен быть установлен в состояние, а затем, когда пользователь нажимает «отправить», в массив может быть добавлен новый объект this.state.expenses .

(Кроме того, ваш handleChange должен указать, какие свойства состояния он намерен изменить)

Ваше окончательное решение должно выглядеть примерно так:

 import React, { Component } from "react";
import ExpenseItem from "./ExpenseItem.js";


class ExpensesList extends Component {
    state = {
        expenses: [{ id: '12345', name: 'Pizza', cost: '20' }],
        cost: "",
        name: ""
    };

    handleChange = (event, name) => {
       this.setState({ [name]: event.target.value });
    };

    handleSubmit = (event) => {
        event.preventDefault();

        let newExpense = {
           id: Math.random(),
           name: this.state.name,
           cost: this.state.cost
        }

        this.setState(prevState => ({
           expenses: [...prevState.expenses, newExpense],   // add new expense to expenses array
           cost: "", // reset this field
           name: "" // reset this field
        }));

    }

    render() {
        return (
            <div>
                <ul className="list-group">
                    {this.state.expenses.map((expense) => (
                        <ExpenseItem
                            id={expense.id}
                            name={expense.name}
                            cost={expense.cost}
                        />
                    ))}
                </ul>
                <div className="row mt-3">
                    <h2> Add Expenses </h2>
                    <form onSubmit={this.handleSubmit}>
                        <div className="row">
                            <div className="form-group">
                                <label for="name">Name</label>
                                <input
                                    required="required"
                                    type="text"
                                    className="form-control"
                                    id="name"
                                    value={this.state.name}
                                    onChange={e => this.handleChange("name")}
                                ></input>
                            </div>
                            <div className="form-group">
                                <label for="name">Cost</label>
                                <input
                                    required="required"
                                    type="text"
                                    className="form-control"
                                    id="cost"
                                    value={this.state.cost}
                                    onChange={e => this.handleChange("cost")}
                                ></input>
                            </div>
                            <div className="form-group">
                                <button type="submit" className="btn btn-primary"> Add Expense</button>
                            </div>
                        </div>
                    </form>
                </div>

            </div>


        );
    }
}

export default ExpensesList;