Shadcn表单中Select组件赋值异常:路由跳转无效刷新才生效
问题分析
使用Shadcn Select组件结合React Hook Form时,路由跳转后Select无法自动选中对应值,但刷新页面正常。核心原因是组件结构、props配置以及状态同步时机的问题。
解决方案
1. 修正FormControl的包裹结构
Shadcn的FormControl需要包裹整个Select组件,而非仅包裹SelectTrigger,这样才能确保表单状态(值、错误提示)正确同步到Select组件。修改后的代码:
<FormField control={form.control} name="title" render={({ field }) => { return ( <FormItem> <FormLabel>Title</FormLabel> <FormControl> <Select onValueChange={field.onChange} value={field.value} > <SelectTrigger> <SelectValue placeholder="Select" /> </SelectTrigger> <SelectContent> <SelectItem value="Doctor">Doctor</SelectItem> <SelectItem value="Mr">Mr</SelectItem> <SelectItem value="Mrs">Mrs</SelectItem> <SelectItem value="Miss">Miss</SelectItem> </SelectContent> </Select> </FormControl> <FormMessage /> </FormItem> ); }} />
2. 移除Select的defaultValue属性
defaultValue仅在组件初始渲染时生效,路由跳转后会干扰React Hook Form受控值的同步。直接移除该属性,完全由field.value控制Select的值。
3. 确保dbUser.title与选项值完全匹配
检查数据库返回的dbUser.title是否和SelectItem的value完全一致(包括大小写、空格)。如果存在格式差异,可统一格式化后再赋值:
useEffect(() => { if (dbUser) { // 统一标题格式,匹配选项值 const normalizedTitle = dbUser.title.charAt(0).toUpperCase() + dbUser.title.slice(1); form.setValue("title", normalizedTitle); form.setValue("firstname", dbUser.firstname); form.setValue("lastname", dbUser.lastname); } }, [dbUser]);
4. 优化useForm默认值配置
给useForm设置明确的初始默认值,避免初始状态下field.value为undefined导致的渲染异常:
const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { title: "", firstname: "", lastname: "", }, });
5. 可选:用form.reset替代多次setValue
如果需要一次性设置多个表单值,使用form.reset比多次setValue更高效,也能确保表单状态同步:
useEffect(() => { if (dbUser) { form.reset({ title: dbUser.title, firstname: dbUser.firstname, lastname: dbUser.lastname, }); } }, [dbUser]);
内容的提问来源于stack exchange,提问作者user3091919
相关产品推荐
相关产品推荐

