工作半年多增删改查(node,mysql,serverless),业务端缺人手。老板好心让我支持其他团队写几页。好久没碰我的手了。除了react,依稀记得antd基本只能看官方demo,一行一行写。中间也遇到了一些熟悉的问题,可惜以前的经验已经没有用了。Demo地址:https://codesandbox.io/s/antd...这些问题在antd的仓库issue中反复提到。看完下文,你将得到以下问题的答案,包括但不限于:总结一下:Form表单,Reacthooks组件,initialValues初始化数据时,第二次,第三次...传新值,表格不更新,一直显示第一个数据?弹出层新建表单重置值不起作用?Modal使用了destroyOnClose,里面包含了Form,使用了form.resetFields,为什么会失败?更新Modal中的initialValues,使用form.resetFields。连续打开两次就生效了?语言描述太苍白了,直接看动图:这是一个简单的增删改查页面。添加和编辑共享相同的组件。期望当弹出的编辑窗体关闭再打开时,可以根据initialValues重新渲染窗体,结果是第二次打开时编辑框没有刷新。实现的伪代码大致是这样的:importReact,{useEffect}from"react";import{Modal,Form,Input,Button,Checkbox}from"antd";exportfunctionEditModal(props){const{visible,onOk,onCancel,content={}}=props;const[form]=Form.useForm();constisEdit=!!内容。种类;consthandleSubmit=(close)=>{//一些提交逻辑};useEffect(()=>{//setTimeout(()=>{form.resetFields();//});},[内容]);返回({...Someforms});}相信大部分有问题的朋友跟我一样,比如上面的代码实现具体问题,具体分析先给出结论,之所以会出现以上问题,主要是三个问题造成的:reacthooks的姿势不正确,antd4form引入hooks,与antd3不同;对form的initialValues理解不清楚;Modal子元素渲染异步,destroyOnClose使用错误;initialValues初始化数据的时候,第二次,第三次……传了新值,表格没有更新?因为initialValues只在窗体第一次初始化时有效,只要窗体没有被卸载重新挂载,改变initialValues不会刷新窗体的值,这是窗体的初衷;下面是initialValues初始化并保存到store的完整实现:??this.setInitialValues=function(initialValues,init){_this.initialValues=initialValues||{};if(init){//setValues的工作方式类似于Object.assign();_this.store=setValues({},initialValues,_this.store);}};this.store存储在表单实例中,只要实例不被销毁,store的值就不会改变。destroyOnClose,弹出层新窗体重置值不起作用?首先,这里有一个概念。当initialValues挂载在一个Form表单实例上时,这个值被存储在hooks生成的表单实例中。所以当我们使用destroyOnClose的时候,虽然Modal和Modal盒子里的Form都被销毁了,但是form实例还是存在的。这个hook实例是挂载在EditModal元素上的,并没有一起销毁,所以当弹窗再次打开时,Form表单会根据这个表单的store重新渲染(原因见上)。Modal使用了destroyOnClose,里面包含了Form,使用了form.resetFields,为什么会失败?当我们意识到表单实例还没有被销毁,可能保存了上次的表单编辑状态时,我们就会想到使用useEffecthook来观察初始值,使用form.resetFields来重置实例,但是最后我们发现那这个不行(我也踩过这个坑)。当我去掉destroyOnClose的时候,发现生效了。后来看了看form.resetFields的实现源码:this.resetFields=function(nameList){varprevStore=_this.store;if(!nameList){//console.log(JSON.stringify(prevStore),JSON.stringify(_this.initialValues));_this.store=setValues({},_this.initialValues);_this.resetWithFieldInitialValue();_this.notifyObservers(prevStore,null,{type:'reset'});返回;此实现与initialValues一样简单,因此问题不在于resetFields。问题出在模态。简单来说,Moda的创建是一个异步的过程,所以子组件的渲染是不同步的。正常的组件渲染如下:就像我上面那样在resetFields中添加一个console,你会发现_this.initialValues是上次的初始值,不是新的(因为Form元素还没有挂载。),所以这里把resetFields调整为寂寞。还有一个简单的方法可以证明Modal组件的子组件挂载是异步的,就是这么玩:useEffect(()=>{setTimeout(()=>{form.resetFields();});},[内容]);这个实现,你会发现resetFields其实已经生效了,因为经过一个宏任务,Form元素已经挂载了。所以这里告诉我们尽量少用destroyOnClose,因为Modal的渲染费时费力。Modal是用form.resetFields初始化的,需要连续打开两次才能生效?相信经过以上一系列的讲解,你心里已经有了答案;destroyOnClose确实不适合在Modal中写表单。那么,在Modal中重新设置ForminitalValues是否正确呢?经过这次经历,我记起来了:destroyOnClose要慎用,因为Modal的渲染开销很大;钩子是个好东西,但你得正确使用它;antd是个好东西,前提是你会用;我还是太擅长了;欢迎关注我的前端公众号:前端黑洞