注:可能在做动态 form 表单时直接写一个 form 表单、使用 Form.list 自己不需要写任何变更原来数据结构的逻辑
若是以上情况可以不需要给表单设置值来变更 form 结构、直接在输入完表单之后、取 form 值提交
但很多情况下,业务都会很复杂、比如选择一项值之后需要给其他表单字段设置对应的值、或后台需要类似城市联动组件中,非value值,此处完全依赖 form 表单自身是很难实现的。
以下只存在于复杂逻辑与数据结构时、需要自己存储一份数据对应到 form 中
bug 代码
class example extends React.Component{
constructor(props) {
super(props);
this.state={
costInfoArr = [{name:""}]
}
}
// 此处做动态添加时、需要先给costInfoArr添加一项、然后通过form.setFieldsValue 设置值;
addInvInfo = () => {
// 此时若直接调用此方法会清空之前的值,因为在执行addInvInfo方法时,我们没有把form表单的值同步到costInfoArr中去 costInfoArr还是最开始的初始值[{name:""}]
const { costInfoArr } = this.state;
costInfoArr.push({
name:""
})
this.setState({costInfoArr});
this.formRef.current.setFieldsValue(costInfoArr)
}
render(){
return (
<Form
ref={this.formRef}
initialValues={{
costInfoArr: costInfoArr,
}}
{...this.tableSearchLayout}
>
<Form.List name="costInfoArr">
{fields =>
fields.map(field => (
<Form.Item name={[field.name, 'name']}>
<Input />
</Form.Item>
))
}
</Form.List>
<Button
type="dashed"
style={{ width: '100%', height: 50 }}
icon={<PlusOutlined />}
onClick={this.addInvInfo}
>
继续添加
</Button>
</Form>
)
}
}
出现此原因的问题主要是因为 Form 组件本身存储了自身的状态值、需要在 每次执行 form.setFieldsValue(costInfoArr) 时,先把之前输入的 form 中的表单值同步到 costInfoArr 中去
正确代码
class example extends React.Component{
constructor(props) {
super(props);
this.state={
costInfoArr = [{name:""}]
}
}
addInvInfo = async () => {
// 在此处之前先调用beforeSetDataSync同步数据
const { costInfoArr } = this.state;
- costInfoArr.push({
- name:""
- })
- this.setState({costInfoArr});
+ try {
+ const costInfoArrCopy = await this.beforeSetDataSync(costInfoArr);
+ costInfoArrCopy.push({
+ name:""
+ })
+ this.formRef.current.setFieldsValue(costInfoArrCopy);
+ this.setState({costInfoArr:costInfoArrCopy});
+ } catch (err) {
+ console.error(err)
+ }
}
+ /**
+ * 同步表单值到存储字段中去
+ * @param {formData} object
+ */
+ beforeSetDataSync = data =>{
+ const formData = JSON.parse(JSON.stringify(data))
+ return new Promise(async (suc, fail) => {
+ try {
+ const values = await this.formRef.current.getFieldsValue()
+ // 此处为业务代码,具体此处如何同步根据业务代码写
+ Object.entries(values).forEach(([key, value]) => {
+ formData[key] = value
+ })
+ suc(formData)
+ } catch (err) {
+ fail(err)
+ }
+ })
+ }
}
还有一种暴力解决方式就是舍弃 Form 组件对自身属性状态管理、直接使用 react 双向绑定、给每个 input 表单加 change 事件、然后变更元数据值