You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'd like to contribute to the development of hook-form's framework agnostic core as well as framework specific adapters.
To accomplish this, I've implemented a framework-agnostic interpretation of react-hook-form with a react adapter that passes all of the tests in the main react-hook-form library.
I've passed all of the tests from react-hook-form and I think it's a solid proof of concept for the core library. I don't intend the react bindings to replace the existing library; I just created them as a baseline for future adapters and to enable me to test the core class functionality.
Next Steps
I'd like to know if there's anything I can do with this work. e.g. Should I open a PR to get things started? My code was written from scratch so there's no base to merge from 🤔
Implementation
Here is a mini-blog post about implementation details. It would be great to have a formal discussion about preparing the project for future development!
Classes
I used a class based approach since it was a lot simpler to model state mutations. One downside is that methods are not auto-bound to their instances, however this is actually a work around for this by using the arrow function syntax, so it's feasible to write the core API as a class, but retain the properties of an object.
Functions/Methods
I tried to use the original method names wherever possible, and I took liberty of adding/removing layers of abstraction to aid the (subjective) readability of the code. This can definitely be refactored as needed and I hope it doesn't detract from the legitimacy of the proof of concept.
Observable
I applied the general idea of writable stores, i.e. the same ones as Svelte, to represent every individual state value. It's possible to subscribe to each one individually. However, React and react-hook-form want to optimize number of render counts by ###batching### updates wherever possible, so I engineered my solution around a batchable observable that can subscribe to multiple stores and only update on certain events.
Batchable
The batchable requires an object that maps keys to observables. For example:
Here, the keys isDirty and isValid are mapped to an observable (writable). The batchable subscribes to both stores, and when either
of them change, the batchable will update itself and notify its own subscribers. i.e. A consumer will subscribe to the batchable, and the batchable will subscribe to all the stores.
Tracking
However, the batchable will only notify for updates with valid combinations of key and context.
Key a key just represents a key in the mapping, for instance "isDirty" and "isValid" are valid string keys to access the object mapping above.
Context a context is an accompanying value, usually a string or string array, that can fine-tune the update.
Practical Example of Tracking
constwritables={values: newWritable({})}constbatchable=newBatchable(writables)batchable.track('values','username')batchable.subscribe(console.log)// NO console.log, since this didn't include the correct context, i.e. "username"writables.values.set({})// YES console.log, this was a change specifically triggered by "username"writables.values.set({},'username')
You want to subscribe to updates to values but only when username triggered the change.
Batching
Finally, to quickly summarize batching, the combinations of changes triggered, e.g. ["values", "username"] might indicate that the store at the "values" key was changed with the "username" context, are stored in a buffer. When the batchable is flushed, all the combinations are parsed, and if any of them are being tracked, then a notification is triggered. Otherwise the batchable is already up to date, but does not send any notifications (and thus doesn't trigger any re-renders).
batchable vs. react-hook-form subjects
React-hook-form manually performs a comparison of the current formState and the next formState, evaluates which keys have changed, etc. whenever deciding whether to render. Although there's definitely a lot of room for refinement, I created the batchable + observable pattern as an alternative where you could 1) cork the batchable, 2) perform any updates needed on any number of observables, 3) flush the batchable and send a single notification if needed.
And this system would hopefully be sophisticated enough where if you followed its documented procedures and understood its behavior well, you wouldn't need to do manual confirmations for each render.
Also because all updates are proxied through this single location, it may be possible to implement additional dev tools that visualize the flow of data in/out of the batchable interface, in addition to building more robust flows like flux on top of it if needed.
The text was updated successfully, but these errors were encountered:
Summary
I'd like to contribute to the development of hook-form's framework agnostic core as well as framework specific adapters.
To accomplish this, I've implemented a framework-agnostic interpretation of react-hook-form with a react adapter that passes all of the tests in the main react-hook-form library.
My work and proof of concept can be found here: https://github.com/ap0nia/forms.js
There is no documentation other than the tests that I've ported over at this time, but I can definitely add anything as needed!
Project Information
I've co-located three packages within the repository.
utils
folder.Key Files
Status
I've passed all of the tests from react-hook-form and I think it's a solid proof of concept for the core library. I don't intend the react bindings to replace the existing library; I just created them as a baseline for future adapters and to enable me to test the core class functionality.
Next Steps
I'd like to know if there's anything I can do with this work. e.g. Should I open a PR to get things started? My code was written from scratch so there's no base to merge from 🤔
Implementation
Here is a mini-blog post about implementation details. It would be great to have a formal discussion about preparing the project for future development!
Classes
I used a class based approach since it was a lot simpler to model state mutations. One downside is that methods are not auto-bound to their instances, however this is actually a work around for this by using the arrow function syntax, so it's feasible to write the core API as a class, but retain the properties of an object.
Functions/Methods
I tried to use the original method names wherever possible, and I took liberty of adding/removing layers of abstraction to aid the (subjective) readability of the code. This can definitely be refactored as needed and I hope it doesn't detract from the legitimacy of the proof of concept.
Observable
I applied the general idea of
writable stores
, i.e. the same ones as Svelte, to represent every individual state value. It's possible to subscribe to each one individually. However, React and react-hook-form want to optimize number of render counts by ###batching### updates wherever possible, so I engineered my solution around abatchable
observable that can subscribe to multiple stores and only update on certain events.Batchable
The batchable requires an object that maps keys to observables. For example:
Here, the keys
isDirty
andisValid
are mapped to an observable (writable). The batchable subscribes to both stores, and when eitherof them change, the batchable will update itself and notify its own subscribers. i.e. A consumer will subscribe to the batchable, and the batchable will subscribe to all the stores.
Tracking
However, the batchable will only notify for updates with valid combinations of
key
andcontext
.Key
a key just represents a key in the mapping, for instance"isDirty"
and"isValid"
are valid string keys to access the object mapping above.Context
a context is an accompanying value, usually a string or string array, that can fine-tune the update.Practical Example of Tracking
You want to subscribe to updates to
values
but only whenusername
triggered the change.Batching
Finally, to quickly summarize batching, the combinations of changes triggered, e.g.
["values", "username"]
might indicate that the store at the "values" key was changed with the "username" context, are stored in a buffer. When the batchable is flushed, all the combinations are parsed, and if any of them are being tracked, then a notification is triggered. Otherwise the batchable is already up to date, but does not send any notifications (and thus doesn't trigger any re-renders).batchable vs. react-hook-form subjects
React-hook-form manually performs a comparison of the current formState and the next formState, evaluates which keys have changed, etc. whenever deciding whether to render. Although there's definitely a lot of room for refinement, I created the batchable + observable pattern as an alternative where you could 1) cork the batchable, 2) perform any updates needed on any number of observables, 3) flush the batchable and send a single notification if needed.
And this system would hopefully be sophisticated enough where if you followed its documented procedures and understood its behavior well, you wouldn't need to do manual confirmations for each render.
Also because all updates are proxied through this single location, it may be possible to implement additional dev tools that visualize the flow of data in/out of the batchable interface, in addition to building more robust flows like flux on top of it if needed.
The text was updated successfully, but these errors were encountered: