依靠循环中的 setState,用键渲染 li

counting on setState in a loop, rendering li with key

我有一个带有项目数组的应用程序 class,它应该有具有唯一 ID 的项目,单击按钮时更新:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  constructor() {
    super();
    this.state = {
      saveId: 1,
      items: []
    };
  }

  addItem(name) {
    let item = {
      id: this.state.saveId,
      name: name
    }
    this.setState({saveId: this.state.saveId + 1});
    let items = this.state.items;
    items.push(item);
    this.setState({items: items});
  }

  updateCount() {
    this.addItem("one");
    this.addItem("two");
    this.addItem("three");
  }

  render() {
    return (
          <div>
                <button
                  onClick={() => this.updateCount()}
                >
                  SaveId: {this.state.saveId}
                </button>
                <ul>
                  {this.state.items.map((item, i) => {
                    return <li key={item.id}>{item.name + "" + item.id}</li>
                  })}
                </ul>
        </div>);
  }
}

export default App;

单击按钮时,将调用 addItem 三次,更新最后保存的 ID 的状态。 updateCount 函数完成后:

this.state.saveId = 2
this.state.items = [
  {
     name: "one",
     id: 1
  },
  {
     name: "two",
     id: 1
  },
  {
     name: "three",
     id: 1
  }
]

即生成一个"Warning: Encountered two children with the same key, 1.".

我知道setState是异步的,循环调用的时候是批量调用的。

我的问题是: 有没有办法绕过它而不直接用 this.state.saveId++ 改变状态?

谢谢。

使用setState函数版本。它会在以前的状态下通过你,你可以用它来制作你的新状态。如果多个设置状态快速连续发生,您可以确定您只会获得最近的状态,而不是设置状态开始发生之前的状态。此外,当您推送到项目时,您目前正在改变旧状态。相反,创建一个新数组,然后添加到其中。

addItem(name) {
  this.setState(prevState => {
    let item = {
      id: prevState.saveId,
      name: name,
    }
    // shallow copy of the array, with an extra item at the end
    const newItems = [...prevState.items, item];
    return {
      items: newItems,
      saveId: prevState.saveId + 1,
    }
  });
}