Håndtering av skjemaer (forms) på en nettside høres i utgangspunktet enkelt ut, men kan fort vise seg å være overraskende komplisert – i hvert fall om du vil ha skikkelig validering av felter, typesikkerhet, og så videre.
Nå har TanStack med Tanner Linsley i spissen kommet med et nytt bibliotek for skjemahåndtering som de hevder skal "revolusjonere hva det betyr å være et type-sikkert skjemabibliotek": TanStack Form v1.
Tanner Linsley er kanskje mest kjent for å ha laget React Query, som nå har byttet navn til TanStack Query, i tillegg til andre verktøy og biblioteker som TanStack Router og TanStack Table.
After 2+ years, it's finally time to announce @TanStack.com Form v1! ✅ Type Safe 🚀 Framework Agnostic 🎭 Headless 🔄 Isomorphic 🛡️ Advanced Validation 📜 Standard Schema ➕ More!
— Tanner Linsley (@tannerlinsley.com) March 3, 2025 at 5:28 PM
[image or embed]
Arbeidet med TanStack Form begynte for to år siden av Linsley selv, men jobben med å lede utviklingen av biblioteket ble ganske raskt delegert til Corbin Crutchley. Og nå er Crutchley og hans team ferdig med versjon 1.0.
– En av fordelene med å "være i ovnen" så lenge, er at TanStack Form lanserer med en masse funksjonalitet du kan ta i bruk fra dag én, skriver Crutchley.
Ekstrem typesikkerhet, innebygget validering
TanStack Form skal være "rammeverk-agnostisk", og støtter fra starten av fem rammeverk: React, Vue, Angular, Solid og Lit.
De fleste verktøyene i TanStack-verktøykassen kjennetegnes av at det er lagt stor vekt på TypeScript-støtte og at det skal være enkelt å bruke. Det gjelder også TanStack Form, der du skal få autofullføring og "inferred" typer overalt.
const form = useForm({
defaultValues: {
name: "",
age: 0
}
});
// TypeScript will correctly tell you that `firstName` is not a valid field
<form.Field name="firstName"/>
// TypeScript will correctly tell you that `name`'s type is a `string`, not a `number`
<form.Field name="name" children={field => <NumberInput value={field.state.value}/>}/>
Det er også typesjekking av feilmeldinger på for eksempel denne måten:
<form.Field
name="age"
validators={{
onChange: ({ value }) => (value < 12 ? { tooYoung: true } : undefined),
}}
children={(field) => (
<>
<NumberInput value={field.state.value} />
// TypeScript will correctly tell you that `errorMap.onChange` // is an object,
not a string
<p>{field.state.meta.errorMap.onChange}</p>
</>
)}
/>
Validering – også asynkront
Validering av skjemaer er selvfølgelig en av hovedgrunnene til å bruke et skjemabibliotek, og her støtter TanStack Form det som kalles Standard Schema – en løsning for å få ulike skjemabiblioteker til å fungere sammen.
Det er støtte for både Zod, Valibot og Arktype "ut av boksen", og du kan for eksempel bruke Zod slik:
const userSchema = z.object({
age: z.number().gte(13, 'You must be 13 to make an account'),
})
function App() {
const form = useForm({
defaultValues: {
age: 0,
},
validators: {
onChange: userSchema,
},
})
return (
<div>
<form.Field
name="age"
children={(field) => {
return <>{/* ... */}</>
}}
/>
</div>
)
}
Ifølge dokumentasjonen har du stor frihet til å velge hvordan og når du vil validere, og validering kan også gjøres asynkront. For eksempel om du vil gjøre et API-kall for å sjekke alderen til en person og bruke dette til å validere et felt i skjemaet:
<form.Field
name="age"
asyncDebounceMs={500}
validators={{
onBlurAsync: async ({ value, signal }) => {
const currentAge = await fetchCurrentAgeOnProfile({ signal })
return value < currentAge ? 'You can only increase the age' : undefined
},
}}
/>
Headless UI-komponenter
I tillegg til å være et rammeverk-agnostisk bibliotek uten noen avhengigheter, har TanStack Form også headless UI-komponenter.
Det betyr at TanStack Form skal være kompatibelt med en masse forskjellige UI-biblioteker, som Material UI, Mantine, Tailwind – eller om du ønsker å bare bruke "vanilla CSS". Det er noen eksempler på hvordan du bruker TanStack Form sammen med ulike UI-biblioteker på denne siden.
Les også om et annet prosjekt fra Tanner Linsley, React-rammeverket TanStack Start:
