reactjs 删除项目后React列表呈现错误数据

fcg9iug3  于 2022-12-22  发布在  React
关注(0)|答案(4)|浏览(229)

我有一个简单的学生对象列表,其中包含名称和他们在州中的分数。
他们的名字绑定到<b>{student.name}</b>,他们的分数绑定到

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

每当我想从这个列表中删除第一个学生并通过调用set state重新呈现组件时。
第二个学生的输入标签显示了第一个学生的分数,而不是有自己的。为什么在我做错的地方会发生这种情况?
Here is my code 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"));
wko9yo5t

wko9yo5t1#

这是因为您使用的是key={index},而不是学生特有的值。
当数组被修改时,删除索引后的学生将具有错误的键,React将不会注册键更改以使用更新的数据重新渲染。
你应该用这样的东西...

<div key={student.name}>

假设student.name是唯一的。

uplii1fm

uplii1fm2#

最好使用unique id作为键,而不是索引。如果你的JSON没有提供unique 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()}
0ve6wy6x

0ve6wy6x3#

最佳实践

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

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 />

一个二个一个一个
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>

然而,在这种情况下,不稳定的键将导致有害的性能,因为组件示例-Virtual DOM和DOM节点-actual DOM将总是不必要的重新创建。
总之,取决于你的数据和行为,你可以选择正确的方式来完成它。

46scxncf

46scxncf4#

'''const getGUID =()=〉“id”+数学.随机().到字符串(16).切片(2);
'''
工作起来很有魅力!

相关问题