React中引用map渲染的输入框的最优方案是什么?
React中获取循环渲染输入框值的高效方案
核心思路:用受控组件替代DOM查询
在React里处理循环生成的输入框,别用document.getElementById——这会绕开React的状态管理逻辑,容易引发视图与数据不一致的问题。最靠谱高效的方案是用受控组件绑定状态,比折腾useRef简单得多,也更符合React的设计理念。
具体实现步骤
- 初始化状态存储输入值
用一个对象保存所有输入框的值,键用每个练习的唯一标识(比如结合分组名和练习名,避免同名称练习冲突):
import { Fragment, useContext, useState } from "react"; import { RoutineContext } from "../../context/CurrentRoutineContext"; export default function Card() { const { data: session, status } = useSession(); const { currentRoutine } = useContext(RoutineContext); // 初始化存储输入值的状态 const [inputValues, setInputValues] = useState({});
- 给输入框绑定状态与变更事件
循环渲染时,给每个输入框绑定value属性和onChange事件,实时更新对应状态:
return ( <> {currentRoutine.sections.map((section) => ( <div key={section.name} className="w-full rounded-md sm:max-w-md sm:shadow-lg"> {/* 头部 */} <div className="px-4 py-5 border-b border-gray-200 shadow-md bg-gravel-400 sm:px-6"> <h3 className="text-xl font-medium leading-6 text-center text-slate-100"> {section.name} </h3> </div> {/* 主体 */} <div className="p-3"> {section.exercises.map((exercise) => { // 生成唯一键,避免同名称练习的输入值冲突 const inputKey = `${section.name}-${exercise.name}`; return ( <div key={exercise.name} className="px-2 py-1.5"> <span className="block font-semibold text-gravel-700">{exercise.name}</span> <table className="min-w-full"> <thead> <tr key={exercise.name}> // 表格表头.... </tr> </thead> <tbody className="divide-y divide-gray-200"> <tr key={exercise.name} className="w-full py-1"> <td className="px-2 text-sm text-gray-500 whitespace-nowrap"> <input type="number" className="w-12 pl-1 text-base rounded-sm bg-gravel-100" value={inputValues[inputKey] || ""} onChange={(e) => { setInputValues(prev => ({ ...prev, [inputKey]: e.target.value })); }} /> </td> <td> <button disabled={false} onClick={() => { // 点击时可直接读取对应输入值 console.log(inputValues[inputKey]); }} type="button" > <CheckIcon className="w-5 h-5 p-1 text-center text-stone-800" /> </button> </td> </tr> </tbody> </table> </div> ); })} </div> </div> ))} </> ); }
- 批量获取输入值
当需要读取所有输入框的值时,直接使用inputValues状态即可,比如提交表单时:
// 示例:添加提交按钮获取所有值 <button onClick={() => console.log("所有输入值:", inputValues)}>提交</button>
实用技巧补充
- 更可靠的唯一标识:如果练习数据里有
id字段,优先用id作为状态的键,比名称更不容易重复; - 默认值初始化:如果需要给输入框设置默认值,可以在组件挂载时,根据
currentRoutine的数据初始化inputValues; - 特殊场景用Ref:如果确实需要操作DOM(比如自动聚焦),可以用
useRef创建一个Map存储每个输入框的ref:const inputRefs = useRef(new Map()); // 循环时给输入框赋值ref <input ref={(el) => el && inputRefs.current.set(inputKey, el)} // ...其他属性 /> // 使用时:比如聚焦指定输入框 inputRefs.current.get(inputKey)?.focus();
内容的提问来源于stack exchange,提问作者Furkan Öz Türk
相关产品推荐
相关产品推荐

