React Hook Form:如何在动态表单中管理每张卡片的独立控件?
问题解决:切换选中卡片时侧边栏设置无法更新
问题背景
开发表单构建页面时,布局为中间展示卡片列表,点击卡片后侧边栏加载对应卡片的配置项。但切换选中卡片时,侧边栏的设置会保留上一张卡片的配置,无法正确更新。尝试过register方法,每次侧边栏开关或切换都会重复注册;改用useController后问题依旧。
问题原因
切换选中卡片时,FocusCard组件的index属性变化,导致useController的name参数(survey.questions.${index}.checked)改变,但useController内部未自动响应该变化重新关联新字段,仍绑定旧字段值。同时组件重新渲染时未强制触发useController更新。
解决方案
给FocusCard组件添加唯一key,确保切换选中项时组件完全卸载重建,让useController重新初始化绑定新字段;此方案简单直接,能快速解决缓存问题。
修改后的代码
import React, { useState } from "react"; import { useForm, useFieldArray, useController } from "react-hook-form"; function FocusCard({ question, index, control }) { const { field } = useController({ name: `survey.questions.${index}.checked`, control, defaultValue: false }); return ( <div> <div>{`Question: ${question.question}`}</div> <label>Check me</label> <input type="checkbox" {...field} /> </div> ); } function QuestionCard({ question, index, setFocus }) { return ( <div className="question" onClick={(e) => setFocus(e, index)}> {question.question} </div> ); } export default function App() { const [selectedIndex, setIndex] = useState(null); const { register, handleSubmit, control, getValues, setValue } = useForm({ defaultValues: { survey: { question: "", questions: [] } } }); const { fields, append } = useFieldArray({ control: control, name: "survey.questions" }); const handleSave = (data) => { console.log(data); }; const handleAddQuestion = (e) => { const newQuestion = getValues("survey.question"); if (newQuestion.trim() !== "") { append({ question: newQuestion, checked: false }); setValue("survey.question", ""); } }; const handleFocus = (e, index) => { setIndex(selectedIndex === index ? null : index); }; return ( <div className="App"> <form onSubmit={handleSubmit(handleSave)}> <h2>Focused Question</h2> {selectedIndex !== null && ( <FocusCard key={`focus-card-${selectedIndex}`} index={selectedIndex} control={control} question={fields[selectedIndex]} /> )} <h2>All Questions</h2> {fields.map((q, i) => ( <QuestionCard key={q.id} question={q} index={i} setFocus={handleFocus} /> ))} <br /> <input type="text" {...register("survey.question")} /> <button type="button" onClick={handleAddQuestion}> Add Question </button> <button type="button" onClick={() => setIndex(null)}>Unfocus</button> <button type="submit">Print Data to Console</button> </form> </div> ); }
关键修改点
- 给
FocusCard组件添加key={focus-card-${selectedIndex}},切换选中项时强制组件卸载重建,让useController重新绑定新字段 - 在
useForm中显式设置defaultValues,确保表单初始状态稳定 - 添加新问题时默认设置
checked: false,避免字段缺失 - 简化
handleFocus逻辑写法
内容的提问来源于stack exchange,提问作者Levy77
相关产品推荐
相关产品推荐

