演示

表单

使用 @quan-erp/shared-ui 的完整 Form 栈:react-hook-form + zod + zodResolver。不要只用 useForm + register()。

标准栈

每个 FormField 都应有 FormMessage。在 frontend/package.json 中声明 react-hook-form、zod、@hookform/resolvers。

  • Form — 展开 useForm 返回值
  • FormField — 通过 render prop 绑定 control + name
  • FormItem / FormLabel / FormControl / FormMessage
  • zod schema + zodResolver
TSXform
1import { zodResolver } from "@hookform/resolvers/zod"; 2import { 3 Button, 4 Form, 5 FormControl, 6 FormField, 7 FormItem, 8 FormLabel, 9 FormMessage, 10 Input, 11} from "@quan-erp/shared-ui"; 12import { useForm } from "react-hook-form"; 13import { z } from "zod"; 14 15const schema = z.object({ 16 email: z.string().min(1, "Email is required").email("Enter a valid email"), 17 password: z.string().min(6, "Password must be at least 6 characters"), 18}); 19 20type FormValues = z.infer<typeof schema>; 21 22export function ExampleForm({ onSubmit }: { onSubmit: (v: FormValues) => void }) { 23 const form = useForm<FormValues>({ 24 resolver: zodResolver(schema), 25 defaultValues: { email: "", password: "" }, 26 }); 27 28 return ( 29 <Form {...form}> 30 <form className="space-y-3" onSubmit={form.handleSubmit(onSubmit)}> 31 <FormField 32 control={form.control} 33 name="email" 34 render={({ field }) => ( 35 <FormItem> 36 <FormLabel>Email</FormLabel> 37 <FormControl> 38 <Input type="email" autoComplete="email" {...field} /> 39 </FormControl> 40 <FormMessage /> 41 </FormItem> 42 )} 43 /> 44 <Button type="submit">Submit</Button> 45 </form> 46 </Form> 47 ); 48}