javascript 如何在React Js中更新useState对象数组而不是添加新的数组元素

eagi6jfj  于 2023-05-21  发布在  Java
关注(0)|答案(2)|浏览(141)

我有一个useState对象,类似于

const [data, setData] = useState({
  dish: "",
  category: "",
  cost: 0,
  qnty: 0,
  img: "",
})

这里qnty是一个计数器变量。每次更新计数器时,data obj也会更新。每次更新data时,都会调用updateCart函数,并更新上下文状态中的值。这里是上下文状态

state = {
  updateCart: this.updateCart,
  cart: [
      {
        dish: "",
        category: "",
        cost: 0,
        qnty: 0,
        img: "",
      }
    ]

updateCart函数

updateCart = (newItem) => {
    this.setState({
      cart: [newItem, ...this.state.cart],
    });
  };

功能运行得非常好。一个新的数组正在添加,这是好的。但是,由于qnty是一个计数器,所以我希望每次调用updateCart时都在上下文状态下更新cart数组,而不是为更新后的qnty添加新行。
例如,如果cart已经有一个qnty为1的元素(对象),如果我将qnty更改为2,则会向cart数组中添加一个新元素。相反,我想将现有的1更新为2。
我该怎么做?
这是我在updateCart函数中尝试过的

updateCart = (newItem) => {
    if (
      this.state.cart.filter(
        (element) => element.dish === newItem.dish && element.dish !== ""
      ).length > 0
    ) {
      const indx = this.state.cart.findIndex(
        (element) => element.dish === newItem.dish
      );
      this.state.cart[indx].qnty = newItem.qnty;
    } else {
      this.setState({
        cart: [newItem, ...this.state.cart],
      });
    }
  };
2guxujil

2guxujil1#

用此更新updateCart函数有助于解决问题

updateCart = (newItem) => {
    if (
      this.state.cart.filter(
        (element) => element.dish === newItem.dish && element.dish !== ""
      ).length > 0
    ) {
      // console.log("inside if");
      const indx = this.state.cart.findIndex(
        (element) => element.dish === newItem.dish
      );
      this.setState(() => {
        this.state.cart[indx].qnty = newItem.qnty;
        // this.state.cart.slice(2);
      });
    } else {
      // console.log("inside else");
      this.setState({
        cart: [...this.state.cart, newItem],
      });
    }
    // console.log(this.state.cart.slice(2));
  };
6qftjkof

6qftjkof2#

这不是更新状态:

this.state.cart[indx].qnty = newItem.qnty;

这是一种“突变”状态,由于各种原因而不好。请注意在工作版本中如何调用this.setState()update state:

this.setState({
  cart: [newItem, ...this.state.cart],
});

无论是更新现有的数组元素还是添加新的数组元素,update state 的操作都不会改变。所有的变化都是如何构造新数组以发送到状态。
通常,用于更新现有项与添加一个新的将是这样的:

- search for a matching existing item
- if one is found
  - create a new shallow copy of that item, updating data as needed
  - set state to a new array containing the copy of the item and all existing items *except* the matching one
- else
  - set state to a new array containing a new item and all existing items

在这两种情况下,需要注意的是,state被设置为一个 new 数组,而不仅仅是修改现有的数组。
这种逻辑的一个例子可能是这样的:

updateCart = (newItem) => {
  if (this.state.cart.find(c => c.dish === newItem.dish && c.dish !== "")) {
    this.setState({
      cart: [...this.state.cart.map(c => {
        if (c.dish === newItem.dish && c.dish !== "") {
          return { ...c, qnty: newItem.qnty }
        } else {
          return c;
        }
      })],
    });
  } else {
    this.setState({
      cart: [newItem, ...this.state.cart],
    });
  }
};

主要的区别(除了将if条件从filter缩短为find和更短的变量名以减少混乱之外)是在设置元素存在的情况下的状态时使用.map()
总的来说,.map()返回一个新的数组,因此以这种方式设置状态是安全的。并且它保留数组的当前顺序。这里对.map()的回调只是检查当前元素是否与条件匹配,如果匹配,则返回一个具有相同值和一个更新值的新元素。对于所有其他元素,它按原样返回元素。

相关问题