我有一个按钮,它可以根据我的状态中设置的数组项目数量添加一个下拉选择。
我可以添加一个新的下拉菜单,但是我很难更新每个下拉菜单的状态值。每次我选择下拉菜单并更改选项时,状态都会恢复到只有1个项目在数组中。
任何想法,我如何能够设置状态与他们的当前值为每个下拉,我有?
state = {
food: [
{name: 'Apple', quantity: 1}
],
};
const addFood = this.state.food.map((item, idx) => {
return
<Dropdown type="food"
className="dropdown-food"
label='food'
key={idx}
value={this.state.food[idx].name}
change={(event) => this.setState({ food: [{ name: event.target.value, quantity: this.state.food[idx].quantity }] })}
/>
})
<Button styleName="add" label="Add Food" clicked={this.addAdditionalFood}/>
我解决了你的问题。现在代码的工作原理和预期的一样:1.当点击按钮时,在状态中添加一个新的下拉菜单和一个新的元素2.当下拉菜单的值发生变化时,它的状态也相应地发生变化。
为了解决这个问题,我只修改了App.js文件中的代码。这里是完整的代码。
import React, { Component } from "react";
import Dropdown from "./Dropdown";
import Button from "./Button";
class App extends Component {
state = {
food: [{
name: "Apple",
quantity: 1
}]
};
addAdditionalFood = () => {
const newState = {...this.state,
food : [...this.state.food,{
name: "Apple",
quantity: 1
} ]};
this.setState(newState);
};
selectFood = (event, index) => {
const newState = {...this.state,
food : [
...this.state.food.slice(0, index),
{
...this.state.food[index],
name: event.target.value,
},
...this.state.food.slice(index + 1)
]};
this.setState(newState);
}
render() {
const addFood = this.state.food.map((item, idx) => {
return (
<Dropdown
type="food"
label="food"
key={idx}
value={this.state.food[idx].name}
change={(event) => this.selectFood(event, idx)}
/>
);
});
return (
<div className="App">
{addFood}
<Button label="Add Food" clicked={this.addAdditionalFood} />
</div>
);
}
}
export default App;
这里是为一个新的下拉菜单添加一个额外状态的代码。
addAdditionalFood = () => {
const newState = {...this.state,
food : [...this.state.food,{
name: "Apple",
quantity: 1
} ]};
this.setState(newState);
};
为了保证状态的不变性,好的做法是不直接对状态进行修改,而是对浅层副本的数据进行操作。在这段代码中,我告诉做一个状态的浅层副本,一个食物的浅层副本,最后,给食物浅层副本添加一个新的值。最后,我设置了新的状态。
这里是改变下拉菜单状态的代码。
selectFood = (event, index) => {
const newState = {...this.state,
food : [
...this.state.food.slice(0, index),
{
...this.state.food[index],
name: event.target.value,
},
...this.state.food.slice(index + 1)
]};
this.setState(newState);
}
这个函数把事件和下拉菜单的索引作为输入;事件中包含了下拉菜单所承担的新值--这个值必须在状态中输入。在这段代码中,我告诉要做一个状态的浅层副本,一个重新排列的食物浅层副本。这个浅层副本是这样构成的:在索引位置前后等于原始的,在索引位置不同。索引位置的元素是原件的浅层副本,但它与原件的区别在于名称。最后,我设置了新的状态。
这里是渲染下拉的代码。
<Dropdown
type="food"
label="food"
key={idx}
value={this.state.food[idx].name}
change={(event) => this.selectFood(event, idx)}
/>
现在它不包含逻辑,只有一个lambda. 不要在jsx里面定义逻辑,而是在类级使用lambda。
如果改变水果的数量,我建议把下拉和输入框包在一起,然后传递给这个新组件两个函数:selectFood和selectQuantity。
注:我为我之前的答案和他们的bug道歉。现在,代码工作了,并且正确应用了不可变性。