React响应式数据更新踩坑
背景
在用户流程结束之后,需要一个类似可编辑表格的界面填写用户评价,用于收集用户使用感受和意见。
但在编写代码的时候发现,UI界面数据更新,响应式数据也随之更新之后,界面并没有重新渲染,导致用户没办法输入任何东西,但是devTool上log输出却是正确的。
主要功能
可编辑表格
使用技术栈
React:17.0.2 - 类组件
antd:4.16.13
解决
当响应式数据为对象数组的时候,浅层拷贝没办法触发React更新,需要深拷贝。
代码实现
仅仅贴出主要代码
DOM
jsx
...
<Table
dataSource={this.state.replyDataTable}
columns={this.replyColumns}
...
/>
...
JS
- 表头配置
jsx
replyColumns = [
...
{
title: "满意度评价,
dataIndex: "MATCH_CASE",
render:(text,row,index) => (
<Rate
onChange={val => this.handleRateChange(val,index)}
value={this.state.replyDataTable[index].MATCH_CASE}
/>
)
}
]
- 当用户编辑时,触发更新
jsx
handleRateChange = (val, index) => {
const {replyDataTable} = this.state;
// 错误做法:浅拷贝, 无法触发render
// const _replyDataTable = [...replyDataTable]
// 正确做法:深拷贝
const _replyDataTable = JSON.parse(JSON.stringify(replyDataTable));
_replyDataTable[index].MATCH_CASE = val;
this.setState({
replyDataTable: _replyDataTable,
})
}
反思
- 在进行更新响应式数据时,要重新拷贝一份引用
- 让我想起了vue2的$set
Vue.js 的响应式系统在初始化时会对数据对象进行递归遍历并设置 getter 和 setter,以便在属性被访问和修改时触发更新。但是,对于已经存在的属性和索引,Vue.js 在初始化时已经设置了 getter 和 setter,因此能够追踪它们的变化。然而,对于新增的属性或索引,初始化时并没有设置相应的 getter 和 setter,导致 Vue.js 无法自动追踪这些变化。