#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;