我想要做的是通过添加用户按下的按钮名称的字符串来更新状态中的数组。用户有几个按钮,所以在按下它们之后,我应该留下一个与用户按下按钮相关的字符串数组。
首先,我给用户一个警告,告诉他们添加了哪些食物然后我只是尝试将该食物的名称附加到状态中的阵列。之后我将该数组传递回父组件以更新类似的数组。
我得到的问题是,当我按下其中一个食物选项时,状态中的数组不会更新,但我确实得到了正确的警报。当我尝试添加第二个食物时,状态中的数组会更新我选择的第一个选项。从那时起每次我尝试添加食物时,状态中的数组会更新我之前选择的食物。
我认为问题在于我正在以React不会立即执行的方式更新状态。我知道React不保证状态更新。
对不起,很长的帖子,谢谢你的时间。
import React from "react";
import "./style.scss";
import FoodData from "./foodData.json";
class Food extends React.Component {
constructor(props) {
super(props);
this.state = {
foodData: [],
addedFoods: []
};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
// Build a new array of objects from FoodData
const newFoodData = FoodData.map(
({ name, pic, serving, calories, sugar, protien }, index) => ({
id: index,
name,
pic,
serving,
calories,
sugar,
protien
})
);
// Assign the new object to state
this.setState({ foodData: newFoodData });
}
handleClick(e) {
alert("Added " + e.target.name);
this.setState(
{
addedFoods: [...this.state.addedFoods, e.target.name]
},
this.props.updateAddedFoods(this.state.addedFoods)
);
}
render() {
const displayFood = () => {
let foodItems = []; // Crate an array
for (let i = 0; i < this.state.foodData.length; i++) {
foodItems.push(
// push item to array through the loop
<div className="food-card" key={i}>
<img src={require(`${this.state.foodData[i].pic}`)} />
<ul>
<li>{this.state.foodData[i].name}</li>
<li>Serving: {this.state.foodData[i].serving}</li>
<li>Calories: {this.state.foodData[i].calories}</li>
<li>Sugar: {this.state.foodData[i].sugar}</li>
<li>Protien: {this.state.foodData[i].protien}</li>
</ul>
<button
onClick={this.handleClick}
name={this.state.foodData[i].name}
>
Add
</button>
</div>
);
}
return foodItems;
};
return (
<div>
<div className="food-container">
{!this.state.foodData.length ? <h1>Loading ...</h1> : displayFood()}
</div>
</div>
);
}
}
export default Food;
setState
的第二个参数应该是函数而不是函数调用。当新状态基于旧状态时,最好使用setState(oldState => newState)
:
handleClick(e) {
const name = e.target.name;
alert("Added " + name);
this.setState(oldState => ({
addedFoods: [...oldState.addedFoods, name]
}),
() => this.props.updateAddedFoods(this.state.addedFoods)
);
}
setState
是异步的,所以当你将this.state.addedFoods
作为参数传递给this.props.updatedAddedFoods
时,你会在改变之前通过状态。由于您似乎在复制数据,我是否可以建议只有父母拥有食物数组并将其作为道具传递给孩子?
所以,正如我在评论中所说,我认为handleClick()
是问题,更确切地说是你如何更新状态。
您可以尝试编写该功能如下:
handleClick(e) {
const newAddedFoods = Object.assign([], this.state.addedFoods);
newAddedFoods.push(e.target.name);
this.setState({addedFoods: newAddedFoods }, () => this.props.updateAddedFoods(newAddedFoods));
}
虽然,@ Iarz是完全正确的:看起来你在父组件和子组件中都有相同的数据。只需将其保留在父组件中,并将子数据和函数传递给子组件以进行更新。