Reputation: 2242
I have a parent react function component (Products
) which shows a list of products and with a state productInfo which is passed as a prop to the child component (AddEditProductModal
)
const Products = () => {
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
const [productInfo, setProductInfo] = useState({});
const showEditModal = async (currentProductInfo) => {
console.log('edit called for key ',currentProductInfo.key)
setIsEditModalVisible(true);
setProductInfo(prevProductInfo => {
return {...prevProductInfo, ...currentProductInfo};
});
};
useEffect(() => {
setIsEditModalVisible(false);
setProductInfo({})
}, []);
return (
<>
<AddEditProductModal
title="Edit Product"
visible={isEditModalVisible}
productInfo={productInfo}
onOk={handleOk}
onCancel={handleCancel}
onFinish={onFinish}
/>
//Table components with columns/actions per row go here
</>
);
};
export default Products;
The child component AddEditProductModal
is an antd Modal/Popup which fills the form with prefilled values chosen for current product row as shown below.
const AddEditProductModal = ({ title, visible, productInfo, onOk, onCancel, onFinish }) => {
return (
<Modal
title={title}
visible={visible}
onOk={onOk}
onCancel={onCancel}
>
<Form
name="basic"
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
onFinish={onFinish}
initialValues = {productInfo}
>
<Form.Item
label="Key"
name="key"
>
<Input disabled={true} />
</Form.Item>
<Form.Item
label="Image"
name="image"
rules={[
{
required: true,
message: "Please input image!",
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Name"
name="name"
rules={[
{
required: true,
message: "Please input name!",
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Price"
name="price"
rules={[
{
required: true,
message: "Please input price!",
},
]}
>
<Input />
</Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form>
</Modal>
);
};
export default AddEditProductModal;
The productInfo is an object containing props as shown below:
{"key":19,"name":"Cooker","image":"https://.....d16bfa6d9c2e010cadc3fe6885448cbd.jpg_720x720q80.jpg","price":123}
When I click on any row's Edit button, the AddEditProductModal
shows correct default values for the product. But when I click on another product/row, the AddEditProductModal
still shows old values even though the productInfo state (seen in the profiler) has changed. Basically, the productInfo state has changed in the parent but the child has not re-rendered is what I am thinking.
Can anyone help why the modal shows the info on the first click but second time, fails to re-render and shows old product info ?
Upvotes: 1
Views: 1872
Reputation: 299
Yes, you are right! First, antd Form's API initialValues
only works when it is initialized or reset. Second, antd Modal won't destroy after the close. So there is the result you said.
method A: do what you said,
useEffect(() => {
form.setFieldsValue(productInfo);
}, [productInfo]);
method B: destroyOnClose property of Modal set true will also solve your issue, but this is not a good choice!
const AddEditProductModal = ({ title, visible, productInfo, onOk, onCancel, onFinish }) => {
return (
<Modal
title={title}
visible={visible}
onOk={onOk}
onCancel={onCancel}
+destroyOnClose+
>
...
Upvotes: 2
Reputation: 2242
I got the answer to my problem. Rather than react, this seemed like an issue with the antd Form component initialValues. Seems like the initialValues does not change and we need to explicitly update the values. Adding the following to my AddEditProductModal solved my issue:
const [form] = Form.useForm();
useEffect(() => {
form.setFieldsValue(productInfo);
}, [productInfo]);
Hope this helps some antd user some day.
Upvotes: 0