簡體   English   中英

反應陣列狀態更新較晚

[英]React Array in State updating late

我想要做的是通過添加用戶按下的按鈕名稱字符串來更新狀態數組。 用戶有幾個按鈕,因此在按下所有按鈕后,我應該留下一個與用戶按鈕按下相關的字符串數組。

首先,我給用戶一個警報,告訴他們添加了哪些食物,然后我只是嘗試將該食物的名稱附加到狀態為數組中。 之后,我將該數組傳遞回父組件以在那里更新一個類似的數組。

我得到的問題是,當我按下食物選項之一時,處於狀態的數組不會更新,但是我確實得到了正確的警報。 當我嘗試第二次添加食物時,狀態數組會使用我選擇的第一個選項進行更新。 從那時起,每次我嘗試添加食物項目時,處於狀態的數組都會用我之前選擇的食物進行更新。

我相信問題在於,我正在以一種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是完全正確的:似乎您在父組件和子組件中都具有相同的數據。 只需將其保留在父組件中,然后將數據和函數傳遞給子組件即可對其進行更新。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM