React动态输入组件问题:单个输入框值无法存入数组
问题原因与解决方法
问题根源
当页面中只有一个name="score"的输入框时,ev.target.elements.score返回的是单个DOM元素,而非多个输入时的HTMLCollection集合。这时候用Array.from(inputs)会错误地将DOM对象的属性当成迭代项处理,导致无法正确获取输入值。另外,getPercent函数里还存在笔误——原本应该获取name="percent"的输入框,却写成了score,这会导致永远拿不到百分比输入框的值。
修复方案
修改getInput和getPercent函数,先把获取到的输入项统一转换成数组格式,不管是单个还是多个输入都能正确处理:
// GET INPUT VALUE const getInput = (ev) => { ev.preventDefault(); const inputs = ev.target.elements.score; // 统一转成数组:单个元素就包装成数组,集合则直接转数组 const inputArray = Array.isArray(inputs) ? inputs : [inputs]; const newScores = inputArray.map((input) => input.value); setValuescore(newScores); }; // GET PERCENT VALUE const getPercent = (ev) => { ev.preventDefault(); const inputs = ev.target.elements.percent; // 修正笔误,从score改为percent const inputArray = Array.isArray(inputs) ? inputs : [inputs]; const newPercents = inputArray.map((input) => input.value); setValuepercent(newPercents); };
完整修改后的代码
import React, {useState} from 'react'; import './button.css'; function DynamicInput() { const [score, setScore] = useState([]); const [percent, setPercent] = useState([]); const [valuescore, setValuescore] = useState([]); const [valuepercent, setValuepercent] = useState([]); const LIMIT = 3; // ADD SCORE INPUT function handleScore() { if (score.length < LIMIT) { setScore([...score, <input key={score.length} type="text" placeholder={'SCORE'} name="score" />]); } } // ADD PERCENT INPUT function handlePercent() { if (percent.length < LIMIT) { setPercent([...percent, <input key={percent.length} type="text" placeholder={'PERCENT'} name="percent" />]); } } // REMOVE INPUT function handleRemove() { if (score.length > 0) { const newInputs = [...score]; const newPercent = [...percent]; newInputs.pop(); newPercent.pop(); setScore(newInputs); setPercent(newPercent); } else { alert('No puedes retirar mas inputs'); } } // GET INPUT VALUE const getInput = (ev) => { ev.preventDefault(); const inputs = ev.target.elements.score; const inputArray = Array.isArray(inputs) ? inputs : [inputs]; const newScores = inputArray.map((input) => input.value); setValuescore(newScores); }; // GET PERCENT VALUE const getPercent = (ev) => { ev.preventDefault(); const inputs = ev.target.elements.percent; const inputArray = Array.isArray(inputs) ? inputs : [inputs]; const newPercents = inputArray.map((input) => input.value); setValuepercent(newPercents); }; return ( <div> <div className="Binputs"> <form id="valueScore" className="content" onSubmit={getInput}> {score.map((input) => input)} </form> <form id="valuePercent" className="content" onSubmit={getPercent}> {percent.map((input) => input)} </form> </div> <button onClick={() => { handleScore(); // handlePercent(); }} > Agregar </button> <button onClick={handleRemove}>Retirar</button> <button type="submit" form="valueScore"> Calcular </button> </div> ); } export default DynamicInput;
额外优化建议
- 不要直接把React元素存在state里,更好的做法是存输入框的数量,渲染时根据数量生成输入框,代码更易维护:
// 用数量代替存元素数组 const [scoreCount, setScoreCount] = useState(0); // 渲染输入框 {Array.from({length: scoreCount}, (_, idx) => ( <input key={idx} type="text" placeholder="SCORE" name="score" /> ))} - 可以将两个表单合并,统一处理提交逻辑,让结构更紧凑。
内容的提问来源于stack exchange,提问作者Noisi
相关产品推荐
相关产品推荐

