React中如何用单个State管理200+输入框?解决值同步问题
如何用单个State管理200+列表输入框
问题背景
我正在开发一个包含200多个列表输入框的项目,想知道是否可以用单个state来管理它们。当前代码存在问题:输入内容时所有输入框会显示相同值,以下是当前使用的代码:
当前代码
List组件
import { useState } from "react"; import Item from "../Components/Item"; const initialState={ input:'' } const List = () => { const [values,setValues]=useState(initialState) const handleChange=(e)=>{ setValues({ ...values,[e.target.name]:e.target.value }) } return ( <div className="container"> <div className="listhead"> <h3 className="text-center">Price List-2022</h3> <table className="table table-bordered border-dark table-hover text-center"> <thead className="bg-success text-white table-bordered border-dark"> <tr> <th>S.No</th> <th>Item</th> <th>Price</th> <th>Qty</th> <th>Total</th> </tr> </thead> <Item product="bomb" name="input" price="50" value={values.input} handleChange={handleChange} /> <Item product="chakkar" name="input" price="100" value={values.input} handleChange={handleChange} /> </table> </div> </div> ); }; export default List;
Item子组件
const Item = ({name,product,price,value,handleChange}) => { return ( <tbody> <tr> <th>1</th> <th>{product}</th> <th>{price}</th> <th className="w-25"> <input name={name} value={value} onChange={handleChange} type='number' /> </th> <th> </th> </tr> </tbody> ); }; export default Item;
问题原因
所有输入框共用了同一个name属性值input,并且绑定的都是values.input这个state字段,导致每次输入时所有输入框读取的是同一个state值,出现内容同步的问题。
可行解决方案
方法一:对象型State+唯一name字段
给每个输入框分配唯一的name(比如产品名称、唯一ID),用对象型state存储每个输入框的值,适合需要单独管理每个输入值的场景:
修改后的List组件
import { useState } from "react"; import Item from "../Components/Item"; // 200个产品建议从外部数据源导入,避免硬编码 const initialItems = [ { product: "bomb", price: "50" }, { product: "chakkar", price: "100" }, // ...其余产品 ]; // 生成初始state,key为产品名,值为空字符串 const initialState = initialItems.reduce((acc, item) => { acc[item.product] = ""; return acc; }, {}); const List = () => { const [values, setValues] = useState(initialState); const handleChange = (e) => { setValues({ ...values, [e.target.name]: e.target.value }); }; return ( <div className="container"> <div className="listhead"> <h3 className="text-center">Price List-2022</h3> <table className="table table-bordered border-dark table-hover text-center"> <thead className="bg-success text-white table-bordered border-dark"> <tr> <th>S.No</th> <th>Item</th> <th>Price</th> <th>Qty</th> <th>Total</th> </tr> </thead> {/* 循环渲染Item,避免重复编写200次 */} {initialItems.map((item, index) => ( <Item key={item.product} product={item.product} name={item.product} // 用产品名作为唯一标识 price={item.price} value={values[item.product]} handleChange={handleChange} serialNumber={index + 1} /> ))} </table> </div> </div> ); }; export default List;
修改后的Item组件
const Item = ({ name, product, price, value, handleChange, serialNumber }) => { const total = parseInt(value) * parseInt(price) || 0; return ( <tbody> <tr> <th>{serialNumber}</th> <th>{product}</th> <th>{price}</th> <th className="w-25"> <input name={name} value={value} onChange={handleChange} type='number' min="0" /> </th> <th>{total}</th> </tr> </tbody> ); }; export default Item;
方法二:数组型State管理完整项数据
如果需要同时管理产品的价格、数量等完整信息,可以用数组型state存储每个项的全部数据,每个数组元素是包含产品信息的对象:
修改后的List组件
import { useState } from "react"; import Item from "../Components/Item"; const initialItems = [ { product: "bomb", price: "50", qty: "" }, { product: "chakkar", price: "100", qty: "" }, // ...其余产品 ]; const List = () => { const [items, setItems] = useState(initialItems); const handleChange = (index, value) => { // 复制数组并更新对应索引的项 const updatedItems = [...items]; updatedItems[index].qty = value; setItems(updatedItems); }; return ( <div className="container"> <div className="listhead"> <h3 className="text-center">Price List-2022</h3> <table className="table table-bordered border-dark table-hover text-center"> <thead className="bg-success text-white table-bordered border-dark"> <tr> <th>S.No</th> <th>Item</th> <th>Price</th> <th>Qty</th> <th>Total</th> </tr> </thead> {items.map((item, index) => ( <Item key={item.product} item={item} serialNumber={index + 1} onQtyChange={(value) => handleChange(index, value)} /> ))} </table> </div> </div> ); }; export default List;
修改后的Item组件
const Item = ({ item, serialNumber, onQtyChange }) => { const total = parseInt(item.qty) * parseInt(item.price) || 0; return ( <tbody> <tr> <th>{serialNumber}</th> <th>{item.product}</th> <th>{item.price}</th> <th className="w-25"> <input value={item.qty} onChange={(e) => onQtyChange(e.target.value)} type='number' min="0" /> </th> <th>{total}</th> </tr> </tbody> ); }; export default Item;
方法三:useReducer管理大规模复杂State
当输入项数量多、更新逻辑复杂时,用useReducer比useState更易维护,将更新逻辑集中在reducer函数中:
List组件使用useReducer
import { useReducer } from "react"; import Item from "../Components/Item"; const initialItems = [ { product: "bomb", price: "50", qty: "" }, { product: "chakkar", price: "100", qty: "" }, // ...其余产品 ]; // 定义reducer处理状态更新 const itemReducer = (state, action) => { switch (action.type) { case "UPDATE_QTY": const updatedState = [...state]; updatedState[action.index].qty = action.value; return updatedState; default: return state; } }; const List = () => { const [items, dispatch] = useReducer(itemReducer, initialItems); return ( <div className="container"> <div className="listhead"> <h3 className="text-center">Price List-2022</h3> <table className="table table-bordered border-dark table-hover text-center"> <thead className="bg-success text-white table-bordered border-dark"> <tr> <th>S.No</th> <th>Item</th> <th>Price</th> <th>Qty</th> <th>Total</th> </tr> </thead> {items.map((item, index) => ( <Item key={item.product} item={item} serialNumber={index + 1} onQtyChange={(value) => dispatch({ type: "UPDATE_QTY", index, value })} /> ))} </table> </div> </div> ); }; export default List;
Item组件与方法二中的实现一致即可。
内容的提问来源于stack exchange,提问作者kishore kumar
相关产品推荐
相关产品推荐

