Ant Design 中 resetFields 导致自定义组件销毁并重新加载问题分析
作者:互联网
在
Form
中使用子组件的过程中发现,每次resetFields
都会导致子组件销毁重建,而子组件由于要请求接口加载数据,所以会导致重复请求。本文记录相关Issues
的查找过程和和相关源码分析
文章目录
一、现象说明
如下代码所示,每次子组件 FormChild
都会打 2
次 log,分析发现是 form.resetFields()
导致子组件重新加载了,而 form.setFieldsValue()
则不会导致组件重新加载
import React from "react";
import ReactDOM from "react-dom";
import { Form } from "antd";
import "antd/dist/antd.css";
import "./index.css";
ReactDOM.render(
<div className="App">
<FormDemo />
</div>,
document.getElementById("root")
);
function FormDemo() {
const [form] = Form.useForm();
React.useEffect(() => {
form.resetFields();
}, [form]);
return (
<Form form={form}>
<Form.Item name="someitem">
<FormChild />
</Form.Item>
</Form>
);
}
function FormChild() {
React.useEffect(() => {
console.log("FormChild mounted");
}, []);
return <div>123</div>;
}
二、官方解释
2.1 官方文档
为什么
resetFields
会重新 mount 组件?
resetFields
会重置整个 Field,因而其子组件也会重新 mount 从而消除自定义组件可能存在的副作用(例如异步数据、状态等等)。
可以看出官方是知道这个问题的,而且这是经过考虑之后的设计方案,所以平时使用的时候需要注意,有些时候更适合 set 而不是 reset
2.2 GitHub Issue
-
① rc-field-form
resetFields会导致自定义组件销毁并重新加载 #106
https://github.com/react-component/field-form/issues/106
-
② antd
form.resetFields() cause Form.Item.children re-mount #29423
https://github.com/ant-design/ant-design/issues/29423
三、源码分析
antd
中 form
的数据处理用了 rc-field-form
,看代码都是 19 年 06 月写的
- ① 对比
resetFields
和setFields
方法可以看出notifyObservers
的type
是明显不同的地方;
- ② 找到观察者响应的代码区域,可以看出两个方法处理的区别,前者
this.refresh()
后者this.reRender()
- ③
refresh
函数有一个明显的标志计数器:resetCount
- ④ 找到计数器
resetCount
使用的区域,发现计数器会导致key
的变化,也就导致了子组件的重新渲染,案情水落石出!
标签:自定义,form,resetFields,Ant,E4%,组件,import,antd 来源: https://blog.csdn.net/zhichaosong/article/details/114373300