#define form api instance externally, consume via react

1 messages · Page 1 of 1 (latest)

nova salmon
#

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 - useFormApi.ts

nova salmon
#

bumping this @bronze goblet . very curious to hear your thoughts on solving this. thanks so much for all your hard work.

bronze goblet
nova salmon
#

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

bronze goblet
#

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

nova salmon
#

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

bronze goblet
# nova salmon hello, i'd like to define my store like `const formApi = new FormApi({...for...

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?
nova salmon
#

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

bronze goblet
#

just the zustand logic that would be cleaner without the useCallback stuff

bronze goblet
#

so that would have to live outside of the react hook lifecycle as well.

nova salmon
#

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

nova salmon
#

i actually have something decent showing up on the screen combining zustand + tanstack react-form. can i add you to a private github repo? @bronze goblet

bronze goblet
nova salmon
#

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

bronze goblet
#

makes sense

nova salmon
#

will push now. what's your github username? also feel free to DM me here

bronze goblet
nova salmon
#

i sent you a DM and added you to the repo!

last willow
#

Hey!

nova salmon
#

hey! can i add you to my DM with Luca?

last willow
#

😄

#

Sure!

#

Sorry for being late to the show

nova salmon
#

no problem, i think this is a fairly legitimate use case. have you gotten into my repo yet?

last willow
#

I have. Had some questions about it, but I'll wait for the DM group chat

nova salmon
#

also it won't let you add me to the DM until you accept my friend request 🙂

last willow
#

Dunno how sensitive this code is to ya

last willow
#

Done

nova salmon
#

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

last willow
#

Fair