React数组映射时状态传递给所有Input组件的问题排查
问题:遍历生成的Input组件共用状态,无法独立输入
我用父表单组件遍历对象数组渲染多个子<Input>组件,但所有输入字段共用同一个状态,输入时所有框同步显示内容。希望每个输入框的值独立存储,比如"全名"和"邮箱"各有自己的状态值,请问哪里错了?
父组件代码
import React, { useState } from 'react'; import { formFieldsData } from './FormFields'; import Input from './Input'; export default function Form() { const [inputValue, setInputValue] = useState(''); const handleChange = (e) => { setInputValue(e.target.value) } return ( <form> {formFieldsData.map((item) => ( <Input key={item.id} id={item.id} label={item.label} type={item.type} placeholder={item.placeholder} inputValue={inputValue} onChange={(e) => handleChange(e)} /> ))} </form> ) }
子组件代码
import React from 'react'; import styles from './forms.module.scss'; import RangeInput from './RangeInput'; export default function Input({ inputValue, onChange, type, id, placeholder = '', label }) { return ( <div className={styles.form__row}> <label htmlFor={id}>{label}: {inputValue}</label> <input required type={type} id={id} name={id} placeholder={placeholder} className={styles.input} value={inputValue} onChange={onChange} /> </div> ) }
formFieldsData.js代码
export const formFieldsData = [ { label: '全名', type: 'text', id: 'fullName', placeholder: '请输入全名' }, { label: '邮箱', type: 'email', id: 'emailAddress', placeholder: '请输入邮箱地址' }, { label: '出生日期', type: 'date', id: 'dateOfBirth', }, { label: '最喜欢的颜色', type: 'color', id: 'favouriteColour', }, { label: '薪资', type: 'range', id: 'salary', }, ];
错误原因
你用了单一字符串状态inputValue,所有Input组件都绑定这个值。不管哪个输入框触发onChange,都会把这个字符串替换成当前输入值,导致所有输入框同步显示相同内容。
修改方案
把状态改成对象类型,每个字段的id作为属性名存储对应输入值,这样每个输入框可以独立更新自己的状态属性。
修改后的父组件代码
import React, { useState } from 'react'; import { formFieldsData } from './FormFields'; import Input from './Input'; export default function Form() { // 初始化状态为对象,每个字段id对应空值 const [formValues, setFormValues] = useState(() => { return formFieldsData.reduce((acc, item) => { acc[item.id] = ''; return acc; }, {}); }); const handleChange = (e) => { const { id, value } = e.target; // 只更新当前输入框对应的属性 setFormValues(prev => ({ ...prev, [id]: value })); } return ( <form> {formFieldsData.map((item) => ( <Input key={item.id} id={item.id} label={item.label} type={item.type} placeholder={item.placeholder} // 传递当前字段对应的状态值 inputValue={formValues[item.id]} onChange={handleChange} /> ))} </form> ) }
说明
- 初始化状态时,用
reduce遍历formFieldsData,生成以每个字段id为键的对象,初始值为空字符串。 handleChange里通过e.target.id拿到当前输入框的标识,只更新对象中对应键的值,其他属性保持不变(用扩展运算符...prev复制之前的状态)。- 渲染Input时,传递
formValues[item.id]作为当前字段的值,每个输入框绑定自己的状态属性。
修改后,每个输入框的值就会独立存储和更新,不会互相影响了。
内容的提问来源于stack exchange,提问作者Connor
相关产品推荐
相关产品推荐

