如何用React-Redux处理map渲染的多输入框并解决NaN问题?
解决React表格总价NaN问题并初始化数量输入框为0
问题根源
你遇到的NaN问题核心来自两个点:
- 初始
qty是空对象,访问未定义的属性返回undefined,和单价相乘直接得到NaN - 数字输入框的
value默认是字符串类型,若不转换直接参与计算,可能引发类型异常
具体修复方案
1. 初始化所有产品的数量为0
当Redux中的产品列表加载完成后,为每个产品生成初始数量0,确保qty对象包含所有产品的键值对:
const [qty, setQty] = useState({}) useEffect(() => { dispatch(fetchList()) }, [dispatch]) // 新增:监听list变化,初始化数量 useEffect(() => { if (list.length) { const initialQty = list.reduce((acc, item) => { acc[item.name] = 0 return acc }, {}) setQty(initialQty) } }, [list])
2. 转换输入值为数字类型
输入框返回的value是字符串,必须转成数字后再存入状态,避免字符串与数字相乘的问题:
const handleChange = (e) => { e.preventDefault() const { name, value } = e.target; // 把输入值转为数字,非数字内容默认设为0 const numValue = isNaN(Number(value)) ? 0 : Number(value) setQty({ ...qty, [name]: numValue }); }
3. 渲染时添加兜底默认值
在计算总价和渲染输入框时,添加?? 0兜底,防止列表未加载完成或状态异常时出现undefined:
// 表格中的总价列 <td>{item.price * (qty[item.name] ?? 0)}</td> // 输入框的value属性 <FormInput type="number" name={item.name} handleChange={handleChange} value={qty[item.name] ?? 0} /> // 计算总金额时的兜底 let sum = 0 list.forEach((item) => { sum += item.price * (qty[item.name] ?? 0) })
修改后的完整代码
import FormInput from './Components/FormInput'; import { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { fetchList } from './Components/Store/action'; function App() { const { list } = useSelector((state) => state.list) const dispatch = useDispatch() const [qty, setQty] = useState({}) const handleChange = (e) => { e.preventDefault() const { name, value } = e.target; const numValue = isNaN(Number(value)) ? 0 : Number(value) setQty({ ...qty, [name]: numValue }); } useEffect(() => { dispatch(fetchList()) }, [dispatch]) useEffect(() => { if (list.length) { const initialQty = list.reduce((acc, item) => { acc[item.name] = 0 return acc }, {}) setQty(initialQty) } }, [list]) let sum = 0 list.forEach((item) => { sum += item.price * (qty[item.name] ?? 0) }) const submitHandler = (e) => { e.preventDefault() } return ( <div > <form onSubmit={submitHandler}> <table> <thead> <tr> <th>S.no</th> <th>Name</th> <th>Unit</th> <th>price</th> <th>Quantity</th> <th>total</th> </tr> </thead> <tbody> {list.map((item) => ( <tr key={item.id}> <td>{item.id}</td> <td>{item.name}</td> <td>{item.unit}</td> <td>{item.price}</td> <td> <FormInput type="number" name={item.name} handleChange={handleChange} value={qty[item.name] ?? 0} /> </td> <td>{item.price * (qty[item.name] ?? 0)}</td> </tr> ))} </tbody> </table> <button type='submit'>Submit</button> </form> <h1>total:{sum}</h1> </div> ); } export default App;
内容的提问来源于stack exchange,提问作者Trunks
相关产品推荐
相关产品推荐

