TanStack / form

🤖 Powerful and type-safe form state management for the web. TS/JS, React Form, Solid Form, Lit Form and Vue Form.

Home Page:https://tanstack.com/form

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Async Fetcher to set up values

enyelsequeira opened this issue · comments

From discord discussion, I think it would be nice a way to have values be async, like after making an api call. Currently React-Hook-Form supports this like so

function App() {
  const values = useFetch("/api")

  useForm({
    defaultValues: {
      firstName: "",
      lastName: "",
    },
    values, // will get updated once values returns
  })
}

one way that we could go about is using the same pattern that tanstack router does it, to have a loader function that will return those values

loader: () => fetchValues()

considerations to take into account

  • Loading times of fetch values (how do you tell the users that an api request is being made)
  • still have default values if the fetch fails

I'm fairly convinced that this would be a mis-step for the Form project. Instead, we have TanStack Query which should be used for async value fetching like this.

To do this, I wonder if it doesn't make sense to do:

const {data} = useQuery({
queryKey: ["test"],
queryFn: getData
})

useForm({
defaultValues: {},
values: data
})

Which should be easy enough to allow. However, the problem is that if data were to change for any reason (refetch, etc) it would trigger values to update, which might not be ideal.

I think you are right, if the data changes, then the values would change, i think the logic would be a bit different, either by setting default query options, then documenting them (could be troublesome changing defaults options)

Turns out that not only do we support this now, but we have for a while - I just hadn't experimented with this enough 😅

import { useForm } from '@tanstack/react-form'
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'

export default function App() {
  const {data, isLoading: loading} = useQuery({
    queryKey: ['data'],
    queryFn: async () => {
      await new Promise((resolve) => setTimeout(resolve, 1000))
      return {firstName: 'Test', lastName: "Two"}
    }
  })

  const form = useForm({
    defaultValues: {
      firstName: data?.firstName ?? '',
      lastName: data?.lastName ?? '',
    },
    onSubmit: async ({ value }) => {
      // Do something with form data
      console.log(value)
    },
  })

  if (loading) return <p>Loading..</p>

  return (
   // ... 
  )
}

Closing, as this should be good enough for our needs, but I'll write a docs page about this soon