QA

Q:如何 Hooks 化做表单逻辑管理?

  1. const form = useForm();

里面实现了类似 FormStore / Model 的能力,并生成 store 对象,便于在 React.FC 类型之中使用 formStore 实例来控制 Form 表单的业务逻辑。

Q:如何优雅组织 Form 及其其它结构?

  • Form
  • Form.List
  • Form.Item
  • Form.useForm:创建 form model 实例;使用 FormStore 的机制来操作表单的所有情况;
  • Form.Provider:实现「子表单域」的 change / submit 处理;

Q:FormProvider 干了啥?如何用?

实现子表单域的 change / submit 处理;

  1. <Form.Provider
  2. onFormFinish={name => {
  3. if (name === 'form1') {
  4. // Do something...
  5. }
  6. }}
  7. >
  8. <Form name="form1">...</Form>
  9. <Form name="form2">...</Form>
  10. </Form.Provider>

值得借鉴

  • React.Context 大量广泛基础语言特性的使用,将 R16 的很多特性发挥得淋漓尽致;
    • 使用 SizeContextProvider 来控制全局 FormSize;
    • 类比:使用 I18nContextProvider 来控制语言;
  • Biz 层抽象为 store,然后用 useForm() 来实现,的确是妙招,实现了数据、业务逻辑与视图层分离;
  • devWarning 很洁癖 😁部分业务代码也值得大规模的复用;可见 DX 还是会给用户带来不少好处的;
devWarning(!!props.name, 'Form.List', 'Miss `name` prop.');

新知

AntD Form 里面对 ref 的使用比较有意思:

  • useImperativeHandle:重写给父组件的当前组件的 Ref;需配合 forwardRef 使用;
  • forwardRef:不常用的东西 GET;Ref forwarding is an opt-in feature that lets some components take a ref they receive, and pass it further down (in other words, “forward” it) to a child.
    • useRef:
// 在 Form.tsx 中,通过 👇 的方式,将 forwardRef 传递的 ref 绑定在 useForm 生成的 formStore
// 上,为此实现 <Form ref={ref} /> 绑定为对应的 formStore,妙啊,妙啊 😄
React.useImperativeHandle(ref, () => wrapForm);

一些思考

  • Form 本质为 表单业务逻辑的抽象,0 UI 代码,只有结构;做到 Input / ComplexInputControls 与 Form 的解耦非常重要
    • 这也是 UI 和业务逻辑分离的经典实践;
  • Form.Field (Item) / List 做表层样式抽象,处理好 Label、Error、Suffix、Prefix 等 UI ;
  • Form.Provider 解决子数据域联动和共享的方法;

Ref