react的diff算法与antd中switch组件不更新问题
问题描述:
现在有个需求,现有一个列表table,里面的数据有启用的也有关闭的,switch组件会根据数据状态展示,同时进行排序,启用数据在前面,未启用的在后面.如图
然后现在需要操作,假如我将第四条数据'的撒管道施工'进行启用,调用启用接口,改变switch组件状态,并重新调用列表查询接口,理想效果,列表数据按启用排序,前三条应该是启用,其他情况是未启用.可实际结果如图
所操作的数据状态确实对了,排序也ok的,但是"第四条数据的switch组件状态没有更新",刷新页面之后,组件更改了.
也就是结果是,switch正确切换了,但是第二次回显还是保留了回显前的状态.代码
代码如下:
{
title: '是否启用',
dataIndex: 'whetherUseing',
key: 'whetherUseing',
// width: 150,
render: (text, record, index) => {
if (text === 1) {
return (
<div
id={`${record.id}${index}${text}`}
// key={`${record.id}${index}${text}`}
>
<Switch
defaultChecked={true}
disabled={!access_enable}
onChange={(value) => startOrEnd(value, record)}
/>
</div>
);
} else {
return (
<p
id={`${record.id}${index}${text}`}
// key={`${record.id}${index}${text}`}
>
<Switch
defaultChecked={false}
disabled={!access_enable}
onChange={(value) => startOrEnd(value, record)}
/>
</p>
);
}
},
},
产生现象的原因:
主要是react的diff算法导致的.diff算法在以下三种情况时会重新构建一个新的DOM树.
(1)当dom的种类发生变化时,比如div变成了p标签
(2)当dom的结构发生变化时,比如由原来的父子结构变成了兄弟结构
(3)当dom的key发生变化时,你可以为dom元素加上key属性,当(1)和(2)不满足时,可以属性发生变化也会导致重新构建dom树
那switch组件这边发生了什么呢?
启用前:switch组件的父元素是一个p标签,打开tab第五栏的开关之后,开关变成了打开状态.接下来就是问题所在,当重新调接口后,该数据确实变成了启用状态,排在了前面(正确),但是,table第四栏的数据是关闭状态,所以逻辑上仍然走else,所以swtich的父元素dom种类没变,dom结构也没变仍是p标签.所以swtich标签以及p标签并不会更新.所以保持了打开状态.其结果就是,明明数据变成了关闭,可switch标签仍是打开状态.简单来说就是.
主体:table的第四栏的swtich(并非是某条数据) 过程:关闭-----(手动打开,此处此时的数据状态仍为关闭,但是swtich的checked属性变成了true)----->>>打开---------(调用接口,数据更新,第四栏的数据更新了,变成了别的数据,而这条数据仍是关闭.switch开关保持原样,checked属性仍为true)------>>打开(更新了,但没完全更新)
解决方案:
给switch标签加上key属性,既然你数据变了,而我也希望你switch也跟着边,那我就把你的key和你的相关数据绑定.根据diff算法特性,只要你key变了,那就会重新渲染
代码:
{
title: '是否启用',
dataIndex: 'whetherUseing',
key: 'whetherUseing',
// width: 150,
render: (text, record, index) => {
if (text === 1) {
return (
<div
id={`${record.id}${index}${text}`}
key={`${record.id}${index}${text}`}
>
<Switch
defaultChecked={true}
disabled={!access_enable}
onChange={(value) => startOrEnd(value, record)}
/>
</div>
);
} else {
return (
<p
id={`${record.id}${index}${text}`}
key={`${record.id}${index}${text}`}
>
<Switch
defaultChecked={false}
disabled={!access_enable}
onChange={(value) => startOrEnd(value, record)}
/>
</p>
);
}
},
},
主体:table的第四栏的swtich(并非是某条数据) 过程:关闭-----(手动打开,此处此时的数据状态仍为关闭,但是swtich的checked属性变成了true)----->>>打开---------(调用接口,数据更新,第四栏的数据更新了,变成了别的数据,而这条数据仍是关闭.在结构和标签类型都不变的情况下,key发生了变化,重新构建渲染)------>>关闭(重新构建一个p标签,并获得 defaultChecked={false} )
最新文章
- 2016 Multi-University Training Contest 1 H.Shell Necklace
- mysql创建数据库
- C++变量和函数
- python模块
- 数据库多对多关联表(Python&;MySQL)
- 2015年9月10-11日,杨学明老师《IPD DRY RUN》专题培训在武汉某上市企业成功举办!
- [redis] session 保存到 redis 简单实现
- js数组小结
- hashcode的一些了解
- undefined 与null的区别与差异
- stl string 容器的使用
- 计蒜客 方程的解数 dfs
- unity(2017.3) C# 常用API
- weui开发笔记
- kafka的安装 (单机)
- 在 Mac 上使用多点触控手势
- Linux中通过/proc/stat等文件计算Cpu使用率
- [转帖]Intel为何吊打AMD,先进半导体工艺带来什么?
- HDU 2807
- Python学习札记(六) Basic3 List和Tuple