[useForm]: eliminate tech debt
- Dominant language
- TypeScript
- Stars
- 247
- Forks
- 78
- Avg merge
- 14h 27m
- Merged PRs (30d)
- 15
Description
## To Do
1. **Remove state from the ref approach**
Previously, we used refs to avoid closures inside hooks and to memoize the form API, ensuring that API callbacks were not recreated on every state change. This was necessary to prevent breaking user components wrapped in `React.memo` that rely on form API methods. We can consider migrating to native state with setState callbacks to always have access to the latest value without needing to include form values in hook dependencies. However, we first need to address the issue of closures in the `Lenses` implementation.
2. **Enable storing form state outside the `useForm` hook**
Add `value` and `onValueChange` props to allow external control of the form state. When these props are provided, the form should operate based on them, similar to the `useFormState` hook.
3. **Lens improvements**:
- **Resolve closure limitations**:
The current `Lens` implementation creates lenses only on mount, providing getters tied to the initial state:
```typescript
const lens = useMemo(
() =>
new LensBuilder({
get: () => formState.current.form,
set: (_, small: T) => {
handleFormUpdate(() => small);
return small;
},
getValidationState: getMergedValidationState,
getMetadata: () => getMetadata(formState.current.form),
}),
[],
);
```
If we move away from the ref-based approach, this will prevent accessing updated values outside closures.
- **Memoize lenses**:
Ensure lenses are memoized to prevent breaking components that receive lenses as props and are wrapped in `React.memo`.
See #2683
Contributor guide
Assessment
This issue has not been assessed yet.