使用react-hook-form的useController结合Tabs时状态异常问题
问题分析与修复方案
核心问题
- 表单提交逻辑错误:
onSubmit写法不正确,未正确调用react-hook-form的提交处理函数 - Tab与表单字段命名不匹配:Tab名称(
tab1/tab2)和初始状态的键(step1/step2)不一致,导致useController无法关联对应字段 - Feature组件取值错误:
useController获取的value已经是当前Tab对应的子对象(如step1的{statement, weight, statements}),但错误尝试访问value.tab1?.statement,应直接访问value.statement
修正后的代码
1. 表单主组件修正
const initialValues = { step1: { statement: '', weight: '', statements: [], }, step2: { statement: '', weight: '', statements: [], }, step3: { statement: '', weight: '', statements: [], }, }; const Form = () => { const methods = useForm({ defaultValues: initialValues }); // 正确绑定提交处理函数 const onSubmit = methods.handleSubmit((data) => { console.log('data: ', data); }); return ( <form onSubmit={onSubmit}> <FormProvider {...methods}> <section> <TabContent // 用initialValues的键作为Tab列表,保证命名一致 tabsList={Object.keys(initialValues)} defaultTab="step1" > {(activeTab) => { console.log('rendering for: ', activeTab); return <Feature tabName={activeTab} />; }} </TabContent> {/* 添加提交按钮触发表单提交 */} <button type="submit">提交</button> </section> </FormProvider> </form> ); }; export default Form;
2. Feature组件修正
import React, { memo, useEffect } from 'react'; import { useController } from 'react-hook-form'; const Feature = ({ tabName }) => { console.log('rendering tab', tabName); // useController关联对应step的字段 const { field: { value, onChange: fieldOnChange }, } = useController({ name: tabName }); const onChangeStatement = (e) => fieldOnChange({ ...value, statement: e.target.value, }); const onChangeWeight = (e) => fieldOnChange({ ...value, weight: e.target.value, }); useEffect(() => { console.log('tabName: ', tabName); console.log('value: ', value); }, [tabName, value]); return ( <> <h1>{tabName}</h1> {/* 直接使用当前Tab对应对象的属性 */} <input onChange={onChangeStatement} value={value.statement} placeholder="输入声明" /> <input onChange={onChangeWeight} value={value.weight} placeholder="输入权重" /> </> ); }; export default memo(Feature);
额外说明
如果你的Tab组件必须使用tab1/tab2作为名称,可在Feature组件中添加映射关系:
const tabToStepMap = { tab1: 'step1', tab2: 'step2', tab3: 'step3' }; // 关联对应字段 const { field } = useController({ name: tabToStepMap[tabName] });
内容的提问来源于stack exchange,提问作者Jeff Goes
相关产品推荐
相关产品推荐

