define form api instance externally, consume via react
hello,
i'd like to define my store like
const formApi = new FormApi({...formOptions})
and still consume it inside of my react components the same way it would work if i used useForm
directly. The source for useForm shows that it just creates the new FormApi
instance inside of a useState lazy initializer, so it would be easy enough to create a useGlobalFormState
hook that does the same thing as what's inside useForm
-- but is this bad practice? is there a reason it's not built in?
my reason for wanting this is: i currently use zustand in my app to store websocket subscriptions and a separate zustand store for form state. within the websocket callback, i dispatch an action to change certain form fields in my form, without involving react renders or useEffect silliness. These actions are not user interactions but messages coming in from a websocket.
this is quite clean and avoids many problems with stale closures, dependency arrays etc, etc. But it seems this is more difficult to achieve with tanstack form. I whipped this up just now, and i think it would work https://gist.github.com/matthewdavi/2d0a6a185d85142b3538170bf6897f0e
for context, my app is fully client side with no SSR and makes heavy use of websockets for updating stateGist
use a store defined at module scope with tanstack form
use a store defined at module scope with tanstack form - useFormApi.ts
24 Replies
eastern-cyanOP•2mo ago
bumping this @Luca | LeCarbonator . very curious to hear your thoughts on solving this. thanks so much for all your hard work.
vicious-gold•2mo ago
hmmm … this warrants a thorough read. I‘ll likely not have time for it today, but I can take a look at it tomorrow
eastern-cyanOP•2mo ago
sounds good. i think it's a legitimate use case that could be solved pretty easily with something like what i wrote in my gist, and it would be very much in the "headless" spirit of tanstack. form logic could be defined externally and truly isolated from the rendering layer. kind of a CSS zen garden for forms
vicious-gold•2mo ago
well, I‘ve heard a lot of history about misuse of hooks before, so that concern may be the reason it hasn‘t been implemented here
but yeah, I can‘t tell until I‘ve given it a read :PepeThumb:
eastern-cyanOP•2mo ago
sounds good. i would be happy to help talk through it tomorrow at some point after you read so we can come up with a good API. thanks again for all your work in here
vicious-gold•2mo ago
putting the formApi outside of the hook would change a lot of the responsibility:
* You are responsible for lifecycle calls (mount, unmount)
* It is your responsibility for updating form options and triggering changes
Additionally, here's some of my thoughts on it so far:
* As far as API goes, since
formOptions
is required to be passed to the FormApi, the change could be as simple as useForm(yourFormApi)
. This is assuming that it no longer takes responsibility for mounting / cleanup and formOptions updates.
* It may just be a wrong usage of a form. If webhooks constantly update form fields, then the user isn't really in control of their own form, which begs the question why it's structured as a form. What kind of websocket subscriptions are you using it for?eastern-cyanOP•2mo ago
wouldn't the formApi still be consumed and mounted by the hook, just available outside of the react lifecycle as well? think of how zustand gives you a single hook that also is the store.
as for the mesages coming in, some of them are populating what could be used as defautlValues, and could be passed in from state into useForm, but there are a few other websocket messages that come in and are responsible for resetting certain fields, and i'd like to be able to consume the form state inside of components that are outside of the form context, maybe i could just hoist it to the top
but i still run into the issue of not being able to synchronously read from the store and get a snapshot of the form state without involving useCallback, it'd be nice to move it fully outside of react's hook lifecycle
vicious-gold•2mo ago
could you create an example snippet of such behaviour? Assume that it's possible to do
useForm(yourExternalFormApi)
and no need to add rendering stuff
just the zustand logic that would be cleaner without the useCallback stuff
If the formApi isn't mounted, then derived values will not be updated properly
so that would have to live outside of the react hook lifecycle as well.eastern-cyanOP•2mo ago
i could try putting something together. give me about an hour since i'll have to recreate something that resembles what i'm doing at work
i actually have something decent showing up on the screen combining zustand + tanstack react-form. can i add you to a private github repo? @Luca | LeCarbonator
vicious-gold•2mo ago
sure! Is it sensitive data, then?
eastern-cyanOP•2mo ago
it's not sensitive at all, the data is fake but it's something i'd rather not have public since it kinda approximates an internal tool
vicious-gold•2mo ago
makes sense
eastern-cyanOP•2mo ago
will push now. what's your github username? also feel free to DM me here
vicious-gold•2mo ago
it‘s linked on my profile, you can alternatively check the contributors page on tanstack.com
eastern-cyanOP•2mo ago
i sent you a DM and added you to the repo!
optimistic-gold•2mo ago
Hey!
eastern-cyanOP•2mo ago
hey! can i add you to my DM with Luca?
optimistic-gold•2mo ago
😄
Sure!
Sorry for being late to the show
eastern-cyanOP•2mo ago
no problem, i think this is a fairly legitimate use case. have you gotten into my repo yet?
optimistic-gold•2mo ago
I have. Had some questions about it, but I'll wait for the DM group chat
eastern-cyanOP•2mo ago
also it won't let you add me to the DM until you accept my friend request 🙂
optimistic-gold•2mo ago
Dunno how sensitive this code is to ya
Oh right. Lemme do that now
Done
eastern-cyanOP•2mo ago
the code itself is not really sensitive but i was kinda lazy and made something similar to an internal tool i've worked on so i'd rather not make it public
optimistic-gold•2mo ago
Fair