问题
我们在使用form组件的时候,如果需要通过form?.getFieldValue的值来,控制某个组件的渲染
例如:
//reat组件
return form?.getFieldValue('name') === '张三' && <>一种展示样式</>
我们印象中使用 form?.getFieldValue('name') 来进行判断,当name='张三'的时候会展示后面的组件。但是这样写并不会触发render的重新渲染,不会更新组件。
方案1:
通常有的同学会联想到使用 useState,创建一个变量来记录name的改变的值,让useState触发重新渲染。但是如果我们需要使用大量的form的表单项的值来控制组件的展示与否,我们会定义大量的useState变量。
方案2:
使用useWatch —监听表单字段,但是这样也会创建大量的useWatch来监听。
const [useform] = Form.useForm();
const nameValue = Form.useWatch(['name'], useform); // 监听对象可以是数组,字符串,数字
console.log("nameValue",nameValue); 每次更新,这里都重新渲染
**组件***
<ProForm
form={useform}
....
>
<ProFormText
label={'用户名称'}
name={'name'} // 监听对象
placeholder={'请输入用户名称'}
rules={[{required: true}]}
/>
</ProForm>
这样的写法看来并不是很优雅。
如何优雅的解决呢?
我们可以通过自定义hooks,然后重写form?.setFieldValue()函数来解决我们创建大量的useState的问题.
自定义hooks
import {useEffect, useState} from "react";
import {FormInstance} from "antd";
/*
针对:form.setFieldValue({name:value})不会触发render,无法使用useEffect监听,不能实现数据双向绑定的效果。
解决问题:不用再注册过多useState来进行数据的监听。
思路: 重写setFieldsValue方法,利用useState进行数据记录
* */
export default function (form: FormInstance<any>) {
const [formField,setFormField] = useState<FormInstance<any> | null>(null)
useEffect(() => {
setFormField(form)
return () => {
setFormField(null)
};
},[form])
const setUseFormFieldValue = (data) => {
_.keys(data)?.forEach((key) => {
form.setFieldsValue({ [key]: data[key] });
})
// 触发组件重新渲染
setFormField({ ...form });
};
return {
useFormField: formField ? {...formField, setFieldsValue: setUseFormFieldValue} : null,
}
}
使用
我这里用的antd的pro组件
import {UseFormFieldsValue} from "@/hooks"; // 我自己定一个hooks名称,你们可以定义成别的
const [useform] = Form.useForm();
const { useFormField } = UseFormFieldsValue(useform);
<ProForm.Item
name={'name'}
label={'名字'}
rules={[{required: true}]}
>
<Input onChange={(value)=>{useFormField?.setFieldsValue({name: value})}}>
</ProForm.Item>