如何在React中通过子组件更新React Hook Form生成的对象数组属性?
解决方案
双表单要不要保留?
留着完全没问题,两个表单职责清晰:一个负责生成投注组合,一个负责批量设置投注金额,没必要强行合并,分开写逻辑更清爽。
核心实现(输入时不触发重渲染)
利用React Hook Form的非受控模式,输入过程中完全不触发组件重渲染,仅在点击提交按钮时一次性收集所有输入值,再批量更新randomBets数组。
父组件改造代码
import { useForm } from "react-hook-form"; // 假设第一个表单提交后生成的randomBets存在useState中 const [randomBets, setRandomBets] = useState([]); // 初始化第二个表单的form实例 const { register, handleSubmit, reset } = useForm(); // 第二个表单的提交处理函数 const onSubmitMultiple = (data) => { // 提交后拿到的data结构为:{ betAmount_0: 10, betAmount_1: 20, ... } const updatedBets = randomBets.map((bet, index) => ({ ...bet, // 将输入值转为数字,未填写时默认设为0 betAmount: data[`betAmount_${index}`] || 0 })); setRandomBets(updatedBets); // 可选:提交完成后重置输入框 reset(); }; // 第二个表单的渲染逻辑 return ( <form className="form" onSubmit={handleSubmit(onSubmitMultiple)}> <div className="display"> <div className="multiple-bet-container"> {randomBets.map((betCombination, index) => ( <MultipleBetBox key={index} index={index} register={register} initialBet={betCombination} /> ))} </div> {randomBets.length > 0 && ( <button className="btn" type="submit"> 应用投注 </button> )} </div> </form> );
子组件MultipleBetBox实现
const MultipleBetBox = ({ index, register, initialBet }) => { return ( <div className="bet-box"> {/* 这里展示投注组合的其他信息,比如initialBet里的赛事、赔率等字段 */} <p>组合信息: {initialBet.matchName} | 赔率: {initialBet.odds}</p> {/* 注册输入框,用索引作为字段名的一部分,确保每个输入框唯一 */} <input type="number" defaultValue={initialBet.betAmount} {...register(`betAmount_${index}`, { valueAsNumber: true, // 自动将输入值转为数字类型 min: 0 // 限制输入不能为负数 })} /> </div> ); };
为什么输入时不会触发重渲染?
React Hook Form的非受控模式下,输入框的值由DOM自身管理,不会触发组件的状态更新,自然也就不会导致重渲染。只有点击提交按钮时,才会调用handleSubmit一次性收集所有输入值,此时更新randomBets状态才会触发一次重渲染。
额外优化建议
- 避免用
index作为key:如果后续randomBets数组有增删操作,建议给每个投注对象添加唯一标识(比如id字段),用id作为key,避免DOM复用导致输入值混乱。 - 增强输入验证:可以在
register中添加更多规则(比如必填、最大值限制),提交时会自动校验,不符合规则则阻止提交。
内容的提问来源于stack exchange,提问作者Matheus Ribeiro
相关产品推荐
相关产品推荐

