涉及到用户输入的组件都要考虑用受控模式还是非受控模式。
value 由用户控制就是非受控模式,由代码控制就是受控模式。
非受控模式就是完全用户自己修改 value,我们只是设置个 defaultValue,可以通过 onChange 或者 ref 拿到表单值。
受控模式是代码来控制 value,用户输入之后通过 onChange 拿到值然后 setValue,触发重新渲染。
单独用的组件,绝大多数情况下,用非受控模式就好了,因为你只是想获取到用户的输入。
受控模式只在需要对用户的输入做一些修改然后再设置到 value 的情况用,再就是实时同步表单值到父组件的时候,比如 Form。
如果需要结合 Form 表单用,那是要支持受控模式,因为 Form 会通过 Store 来统一管理所有表单项。
封装业务组件的话,用非受控模式或者受控都行。
有的团队就要求组件一定是受控的,然后在父组件里维护状态并同步到状态管理库,这样组件重新渲染也不会丢失数据。
但是基础组件还是都要支持,也就是支持 defaultValue 和 value + onChange 两种参数,内部通过判断 value 是不是 undefined 来区分。
写组件想同时支持受控和非受控,可以直接用 ahooks 的 useControllableValue,也可以自己实现。
arco design、ant design 等组件库都是这么做的,并且都封装了类似的合并受控/非受控值的 hook(如 arco 的 useMergeValue、antd 的 useMergedState),我们也封装了一个。
理清受控模式和非受控模式的区别,在写组件的时候灵活选用或者都支持。