如何向列表中添加新元素?

时间:2020-12-18 21:25:19

标签: javascript arrays reactjs

我试图通过更新一个属性 (id) 将数组的一个新元素添加到列表中。我想让它比数组长度多 1。 但是我得到了一些奇怪的输出,添加了每个新对象。所有元素都获得 array.length +1 值。

我使用 letconst 甚至直接在 this.state.produktsToBuy 上操作对这段代码做了几个变体,每次都得到相同的输出

enter image description here

handleAddToShop = (produktToBuy) => {
  const id = this.state.produktsToBuy.length+1;
  produktToBuy.id = id + 1;
  const produktsToBuy = this.state.produktsToBuy;
  produktsToBuy.push(produktToBuy);
  this.setState({produktsToBuy});
};

我应该得到输出为 1,2,3,4,5,6,7 但最后我得到 7,7,7,7,7,7

2 个答案:

答案 0 :(得分:1)

确保您没有直接改变状态。在 JS 中,对象是一种引用类型。当您将 this.state.produktsToBuy 分配给 const produktsToBuy 并将某些内容推送到 produktsToBuy 时,您实际上是在推送原始 this.state.produktsToBuy 并修改状态。

您可以使用扩展运算符 (...) 创建状态 (produktsToBuy) 的浅表副本:

class App extends React.Component {
  state = {
    items: [
      { name: "test item 1", price: 4.99 },
      { name: "test item 2", price: 7.99 },
      { name: "test item 3", price: 19.99 }
    ],
    produktsToBuy: []
  };

  handleAddToShop = (produktToBuy) => {
    this.setState((prev) => ({
      produktsToBuy: [
        ...prev.produktsToBuy,
        {
          ...produktToBuy,
          id: prev.produktsToBuy.length + 1
        }
      ]
    }));
  };

  render() {
    return (
      <div className="App">
        <div style={{ display: "flex" }}>
          {this.state.items.map((item) => (
            <div
              key={item.name}
              style={{
                border: "1px solid #ccc",
                margin: "1rem",
                padding: "1rem",
                textAlign: "center"
              }}
            >
              <h3>{item.name}</h3>
              <p>${item.price}</p>
              <button onClick={() => this.handleAddToShop(item)}>Add</button>
            </div>
          ))}
        </div>
        <pre>{JSON.stringify(this.state.produktsToBuy, null, 2)}</pre>
      </div>
    );
  }
}


ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

如果除了 produktsToBuy 之外还有其他任何东西,您应该保持之前的所有状态。此外,如果您设置的任何内容都依赖于先前的状态(通常情况下),您总是需要 setState 的功能形式。而且,就像 Zsolt 所说的,你永远不会直接在 React 中改变状态。这是我的答案(与@Zsolt Meszaros 非常相似)。注意:.concat 创建了一个新数组,所以我们不必担心改变原始数组。

handleAddToShop = (produktToBuy) => {
    this.setState((prevState) => {
        const { produktsToBuy } = prevState;
        return {
            ...prevState,
            produktsToBuy: produktsToBuy.concat([
                {
                    ...produktToBuy,
                    id: produktsToBuy.length + 1,
                },
            ]),
        };
    });
};