QA
Q:如何 Hooks 化做表单逻辑管理?
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 处理;
<Form.Provider
onFormFinish={name => {
if (name === 'form1') {
// Do something...
}
}}
>
<Form name="form1">...</Form>
<Form name="form2">...</Form>
</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
- rc-form-field 核心实现,是基于 rc 来实现的;