React antd如何让自定义组件与Form双向绑定?

1,000 阅读1分钟

项目开发过程中,我们最常用到的就是Form表单,无论是Vue配合使用的ElementUI,还是React常用的Antd,都会自带表单组件。一般情况下,这些表单组件只适配了常用的表单元素(文本输入框、密码框、数字输入框、复选框、单选按钮、下拉列表、文本域等),在进行提交或校验时直接通过表单实例操作即可,那么,如何将我们自定义的组件也能够像表单元素一样与Form进行数据双向绑定呢?

众所周知,表单元素之所以能进行数据双向绑定是因为valueonChange两个属性,在React中,虽然没有数据双向绑定的概念,但我们依然可以借助这两个属性让自定义组件与Form进行交互,从而模拟数据的双向绑定。

父组件示例代码:


... ...

const [form] = Form.useForm();
const onFinish = values => {
     // { username: '', password: '', count: '' }
    console.info(values);
};
  
      <Form labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} initialValues={initialValues} onFinish={onFinish} autoComplete="off">
        <Form.Item label="Username" name="username" rules={[{ required: true, message: 'Please input your username!' }]}>
          <Input />
        </Form.Item>
        <Form.Item label="Password" name="password" rules={[{ required: true, message: 'Please input your password!' }]}>
          <Input.Password />
        </Form.Item>
        <Form.Item label="custom" name="count" rules={[{ required: true, message: 'Please check value' }]}>
          <Child />
        </Form.Item>
        <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
          <Button type="primary" htmlType="submit">
            Submit
          </Button>
        </Form.Item>
      </Form>
 ... ...

自定义子组件示例代码:

function Child(props) {
  const { value, onChange } = props;
  const [count, setCount] = useState<number>(value);

  useEffect(() => {
    count !== undefined && onChange?.(count);
  }, [count]);
  return (
    <div>
      {count}
      <Button
        onClick={() => {
          setCount(prev => Number(prev || 0) + 1);
        }}
      >
        +1
      </Button>
    </div>
  );
}

在上面的示例中,valueonChange是关键。Form组件内部通过context提供了表单的上下文,当表单项(即 Form.Item 的子元素)注册到Form时,它们会接收到一个特殊的 value 和 onChange(或类似的,如 onSelectonCheck 等,取决于具体的表单元素)属性。这样在子组件中触发onChange事件时Form组件会自动处理。 这样一来,我们很多自定义开发的组件就可以与Form组件绑定,从而借助于Form的表单校验等达到很好的用户体验。