删除项目后反应列表呈现错误数据

时间:2017-04-26 18:53:23

标签: reactjs react-dom

我有一个简单的学生对象列表,其名称和状态分数。

他们的名字绑定到<b>{student.name}</b>,他们的分数必然会

<input type="text" defaultValue={student.score}/>

什么时候我想从这个列表中删除第一个学生 通过调用set state

重新呈现组件

第二个学生的输入标签显示第一个学生的分数而不是拥有自己的分数。为什么这会发生在我做错的地方?

这是我的代码here is mycode in jsbin

class App extends React.Component{
  constructor(){
    super();
    this.state ={
      students:[{name:"A",score:10},{name:"B",score:20},{name:"C",score:30}]
    }
  }

  onDelete(index){
    this.state.students.splice(index,1);
    this.setState(this.state);
  }

   render(){
     return(
       <div>
         {this.state.students.map((student,index)=>{
              return(
                <div key={index}>
                    <b>{student.name}</b> - <input type="text" defaultValue={student.score}/>
                     <button onClick={this.onDelete.bind(this,index)}>delete</button>
                </div>                
              )
         })}
       </div>
     )
   }
}


ReactDOM.render(<App/>,document.getElementById("main"));

3 个答案:

答案 0 :(得分:12)

这是因为您使用key={index}而不是学生唯一的值。

当数组被修改后,删除索引后的学生将使用错误的密钥,并且React不会注册密钥更改以使用更新的数据重新呈现。

你应该改用这样的东西......

<div key={student.name}>

假设student.name是唯一的。

答案 1 :(得分:2)

使用唯一ID作为键而不是索引总是更好。如果您的JSON没有提供唯一的ID,您可以使用类似uuid npm模块的东西来为您生成它。这是链接https://www.npmjs.com/package/uuid

然后您可以导入它并使用如下

import { v4 } from 'uuid'; //there are 5 versions. You can use any.

然后通过调用v4函数(如下面的

)使用它来生成uique Id
id={v4()}

答案 2 :(得分:0)

最佳做法

老实说,你不应该直接改变状态数据。你应该克隆然后像这样完成你的任务

onDelete(index) {
    const newStudents = [...this.state.students];
    newStudents.splice(index, 1);
    this.setState({ students: newStudents });
}

Why can't I directly modify a component's state, really?

<块引用>

previous state 将被您的突变污染。因此,两个状态的浅比较和合并将是 不安或不会发生,因为你现在只有一种状态。 这将破坏 React 的所有生命周期方法。


您的问题和解决方案

  1. 如果您使用输入 readOnly,您应该将 defaultValue 更改为 value ,然后您的代码运行良好。
<input type="text" value={student.score} readOnly />

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      students: [
        { name: "A", score: 10 },
        { name: "B", score: 20 },
        { name: "C", score: 30 }
      ]
    };
  }

  onDelete(index) {
    const newStudents = [...this.state.students];
    newStudents.splice(index, 1);
    this.setState({ students: newStudents });
  }

  render() {
    return (
      <div>
        {this.state.students.map((student, index) => {
          return (
            <div key={index}>
              <b>{student.name}</b> -{" "}
              <input type="text" value={student.score} readOnly />
              <button onClick={this.onDelete.bind(this, index)}>delete</button>
            </div>
          );
        })}
      </div>
    );
  }
}

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

<div id="app"></div>

  1. 否则,您应该提供唯一的 key。如果 student.name 不是唯一的,您可以像这样随机 GUID
const getGUID = () => "id" + Math.random().toString(16).slice(2);
>  <div key={getGUID()}>

const getGUID = () => "id" + Math.random().toString(16).slice(2);

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      students: [
        { name: "A", score: 10 },
        { name: "B", score: 20 },
        { name: "C", score: 30 }
      ]
    };
  }

  onDelete(index) {
    const newStudents = [...this.state.students];
    newStudents.splice(index, 1);
    this.setState({ students: newStudents });
  }

  render() {
    return (
      <div>
        {this.state.students.map((student, index) => {
          return (
            <div key={getGUID()}>
              <b>{student.name}</b> -{" "}
              <input type="text" defaultValue={student.score} />
              <button onClick={this.onDelete.bind(this, index)}>delete</button>
            </div>
          );
        })}
      </div>
    );
  }
}

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

<div id="app"></div>

但是,在这种情况下,Unstable 键将 cause harmful performance,因为组件实例 - Virtual DOM 和 DOM 节点 - actual DOM 将总是不必要的重新创建。

简而言之,根据您的数据和行为,您可以选择正确的方式来完成它。

相关问题