TanStack Form Demo
Learn how to generate a TanStack Form from a Candid method: FieldVisitor
turns the method’s argument types into field metadata, default values and a
Zod schema, and one component renders every field from that metadata. The demo
builds the form for an updateProfile(UserProfile) IDL and shows the submitted
values; it does not call a canister.
Features Demonstrated
Section titled “Features Demonstrated”- Generated Fields: One field per Candid type, chosen by
field.component(records, variants, optionals, vectors, text, numbers, booleans). - Defaults:
meta.defaultsseeds the form. - Validation:
meta.schemavalidates every change.
Open in StackBlitzEdit and run in your browser
View on GitHubBrowse the source code
Live Preview
Section titled “Live Preview”Implementation
Section titled “Implementation”import { FieldVisitor } from "@ic-reactor/candid"import { IDL } from "@icp-sdk/core/candid"import { useForm } from "@tanstack/react-form"
const UserProfile = IDL.Record({ username: IDL.Text, age: IDL.Nat, email: IDL.Text, bio: IDL.Opt(IDL.Text), tags: IDL.Vec(IDL.Text),})
const visitor = new FieldVisitor()const meta = visitor.visitFunc(IDL.Func([UserProfile], [], []), "updateProfile")
function CandidForm() { const form = useForm({ defaultValues: meta.defaults, validators: { onChange: meta.schema }, onSubmit: async ({ value }) => { console.log("Form Submitted:", value) }, })
return ( <form onSubmit={(e) => { e.preventDefault() form.handleSubmit() }} > {meta.args.map((field, index) => ( <DynamicField key={field.name || index} field={field} form={form} /> ))} <button type="submit">Submit</button> </form> )}DynamicField is the demo’s own component (in src/App.tsx): it renders one
FieldNode with the input its component names.
To send the values to a canister, convert them from display types to Candid first; see CandidFormVisitor.