form
form copied to clipboard
Async Fetcher to set up values
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
Hey @crutchcorn, this only works for me in dev mode. Once I preview it or deploy a production build, it stops working. In other words, all fields stay blank and don't capture server values.