T
TanStack3mo ago
eastern-cyan

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 state
Gist
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-cyan
eastern-cyanOP2mo ago
bumping this @Luca | LeCarbonator . very curious to hear your thoughts on solving this. thanks so much for all your hard work.
vicious-gold
vicious-gold2mo 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-cyan
eastern-cyanOP2mo 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
vicious-gold2mo 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-cyan
eastern-cyanOP2mo 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
vicious-gold2mo 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 formOptionsis 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-cyan
eastern-cyanOP2mo 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
vicious-gold2mo 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-cyan
eastern-cyanOP2mo 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
vicious-gold2mo ago
sure! Is it sensitive data, then?
eastern-cyan
eastern-cyanOP2mo 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
vicious-gold2mo ago
makes sense
eastern-cyan
eastern-cyanOP2mo ago
will push now. what's your github username? also feel free to DM me here
vicious-gold
vicious-gold2mo ago
it‘s linked on my profile, you can alternatively check the contributors page on tanstack.com
eastern-cyan
eastern-cyanOP2mo ago
i sent you a DM and added you to the repo!
optimistic-gold
optimistic-gold2mo ago
Hey!
eastern-cyan
eastern-cyanOP2mo ago
hey! can i add you to my DM with Luca?
optimistic-gold
optimistic-gold2mo ago
😄 Sure! Sorry for being late to the show
eastern-cyan
eastern-cyanOP2mo ago
no problem, i think this is a fairly legitimate use case. have you gotten into my repo yet?
optimistic-gold
optimistic-gold2mo ago
I have. Had some questions about it, but I'll wait for the DM group chat
eastern-cyan
eastern-cyanOP2mo ago
also it won't let you add me to the DM until you accept my friend request 🙂
optimistic-gold
optimistic-gold2mo ago
Dunno how sensitive this code is to ya Oh right. Lemme do that now Done
eastern-cyan
eastern-cyanOP2mo 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
optimistic-gold2mo ago
Fair

Did you find this page helpful?