错误使用antd的form表单中的initialValue属性导致的问题。
场景还原
在某个场景中需要点击按钮打开一个弹窗, 弹窗内容为一个表单, 表单某一项是获取的点击按钮前选中的某项数据。
代码还原
index.tsx
import * as React from 'react';
import { Button } from 'antd';
import { useModalData } from './index.hooks';
import ModalTest from './ModalTest';
export default function Demo() {
const { show, handleClick, selectData, handleChange, closeModal } = useModalData();
const generateList = () => {
const list = ['test-id', 'group-id', 'program-id', 'menu-id'];
return (
<div>
{list.map(item => {
return (
<Button onClick={() => handleChange(item)} key={item}>
{item}
</Button>
);
})}
</div>
);
};
return (
<>
<Button onClick={handleClick}>打开弹窗</Button>
{generateList()}
<ModalTest show={show} selectData={selectData} closeModal={closeModal} />
</>
);
}
index.hooks.ts
import React from 'react';
export const useModalData = () => {
const [show, setShow] = React.useState(false);
const handleClick = () => {
console.log(selectData)
setShow(true);
}
const [selectData, setSelectData] = React.useState('test-id');
const handleChange = (value:string) => {
console.log(value)
setSelectData(value)
}
const closeModal = () => {
setShow(false);
}
return { show , handleClick , selectData, handleChange, closeModal }
}
ModalTest.tsx
import * as React from 'react';
import { Modal, Form, Input } from 'antd';
const ModalTest = (props: any) => {
return (
<Modal
maskClosable={false}
title="Basic Modal"
visible={props.show}
onCancel={props.closeModal}
>
<Form>
<Form.Item name="test_id" label="测试" initialValue={props.selectData}>
<Input readOnly={true} />
</Form.Item>
</Form>
</Modal>
);
};
export default ModalTest;
效果图
可以看到第二次点击后弹窗里内容还是显示的上一次的值。查了下antd官网后发现问题原因是该属性只在初始化以及重置时生效。
两种方法解决:
- 在
ModalTest中的useEffect中使用Form的setFields方法(或者setFieldsValue)并且移除initalValue。
const ModalTest = (props: any) => {
const [form] = useForm();
//添加 useEffect
React.useEffect(() => {
props.show &&
// form.setFieldsValue({ test_id: props.selectData });
form.setFields([
{
name: 'test_id',
value: props.selectData,
},
]);
}, [props.selectData, props.show]);
return (
<Modal
maskClosable={false}
title="Basic Modal"
visible={props.show}
onCancel={props.closeModal}
>
<Form form={form}>
//移除 initalValue
<Form.Item name="test_id" label="测试">
<Input readOnly={true} />
</Form.Item>
</Form>
</Modal>
);
};
- 在
ModalTest中的useEffect中使用Form的resetFields方法。
const ModalTest = (props: any) => {
const [form] = useForm();
//添加 useEffect
React.useEffect(() => {
props.show && form.resetFields();
}, [props.show]);
return (
<Modal
maskClosable={false}
title="Basic Modal"
visible={props.show}
onCancel={props.closeModal}
>
<Form form={form}>
<Form.Item name="test_id" label="测试" initialValue={props.selectData}>
<Input readOnly={true} />
</Form.Item>
</Form>
</Modal>
);
};
修复后效果:
总结: 虽然是一个很简单的问题, 但是还是因为在工作中粗心导致出现了这样的bug, 在代码复审中被leader的火眼金晴抓了出来。故以此文记录, 希望以后的我能更加的仔细, 认真。