简体   繁体   中英

How can I add new elements to a list?

I was trying to add a new element of array to the list with update of one property (id). I want to make it 1 more than length of array. But I get some weird outputs, with add every new object. All elements are getting array.length +1 value.

I made several variations of this code with let , const or even operating directly on this.state.produktsToBuy , and every time I got the same output

在此处输入图像描述

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

I Should get the output as 1,2,3,4,5,6,7 But on the end I get 7,7,7,7,7,7

Make sure you're not mutating the state directly. In JS, objects are a reference type. When you assign this.state.produktsToBuy to const produktsToBuy and push something to produktsToBuy , you're actually pushing to the original this.state.produktsToBuy and you modify the state.

You can use the spread operator ( ... ) to create a shallow copy of the state ( 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>

You should be maintaining all of the previous state if there's anything other than just the produktsToBuy. Also, you always need the functional form of setState if anything you're setting is dependent on the previous state(as is OFTEN the case). And, like Zsolt said, you never mutate the state directly in React. Here's my answer (very similar to @Zsolt Meszaros'). Note: .concat creates a new array, so we don't have to worry about mutating the original.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM