如何修复React组件(使用useCallback钩子)中无数字输入时生成空白'NaN'项的问题
如何修复React组件(使用useCallback钩子)中无数字输入时生成空白'NaN'项的问题
我来帮你解决这个问题!首先咱们先分析一下为什么会出现NaN,然后一步步修复它~
首先,你的代码里有两个核心问题导致了NaN的出现:
- 输入框为空时,
parseInt(e.target.value)会返回NaN,让Parent组件的number状态变成NaN,最终getItems返回的数组全是NaN; - Child组件里有个小bug:
useEffect中直接把props.getItems(这是一个函数)赋值给了items,而没有调用这个函数获取数组!
接下来咱们一步步修复:
步骤1:修复Child组件的函数调用错误
在Child组件的useEffect里,你需要调用props.getItems()来获取数组,而不是直接把函数本身存到items里。如果不调用函数,items会被设置成一个函数,后续map的时候会直接报错,这也是当前代码的隐藏问题~
修改后的Child组件useEffect部分:
useEffect(() => { setItems(props.getItems()); // 这里要调用函数,而不是传函数本身 console.log('Updating List items') }, [props.getItems])
步骤2:处理输入框的空值,避免number变成NaN
当输入框为空时,parseInt("")会返回NaN,这会让number状态变成NaN,进而导致生成的数组项全是NaN。我们可以在输入处理时给空值设置默认逻辑,这里提供两种方案供你选择:
方案A:空值时设为0(保持数组始终有3项)
如果你希望输入框为空时仍显示3个数字项,可以把空值默认设为0:
修改Parent组件的输入框onChange事件:
<input type="number" value={number} onChange={e => { const inputValue = e.target.value; // 若输入为空,设为0;否则转成数字 setMyNumber(inputValue ? parseInt(inputValue, 10) : 0); }} />
方案B:空值时数组为空(不显示任何项)
如果你希望输入框为空时隐藏整个列表,可以把number设为null,然后在getItems里判断:
首先修改Parent的输入框onChange和value:
<input type="number" value={number || ''} // 空值时输入框显示为空 onChange={e => { const inputValue = e.target.value; setMyNumber(inputValue ? parseInt(inputValue, 10) : null); }} />
然后修改getItems函数:
const getItems = useCallback(() => { // 如果number是null,返回空数组;否则返回数字数组 if (number === null) return []; return [number, number + 1, number + 2]; }, [number])
步骤3:额外的安全过滤(可选,双重保险)
为了彻底避免NaN出现在列表中,你可以在生成数组时过滤掉无效的数字,比如在Parent的getItems里:
const getItems = useCallback(() => { return [number, number + 1, number + 2].filter(item => !isNaN(item)); }, [number])
这样即使number不小心变成了NaN,过滤后数组会是空的,不会渲染出NaN项。
最终修复后的完整代码参考
ParentComp.jsx
import React , {useCallback, useState} from 'react' import Childlist from './Childlist' function ParentComp() { const [number, setMyNumber] = useState(1) const [dark, setTheme] = useState(false) const getItems = useCallback(() => { if (number === null) return []; return [number, number + 1, number + 2].filter(item => !isNaN(item)); }, [number]) const theme = { backgroundColor: dark? '#333': '#FFF', color: dark ? '#FFF' : '#333' } return ( <div style={theme}> <input type="number" value={number || ''} onChange={e => { const inputValue = e.target.value; setMyNumber(inputValue ? parseInt(inputValue, 10) : null); }} /> <button onClick={() => setTheme(prevDark => !prevDark)}> Toggle Theme </button> <Childlist getItems={getItems}/> </div> ) } export default ParentComp
Childlist.jsx
import React, { useEffect, useState } from 'react' function Childlist(props) { const [items, setItems] = useState([]) useEffect(() => { setItems(props.getItems()); // 修复:调用函数获取数组 console.log('Updating List items') }, [props.getItems]) return items.map((each_item) => <div key={each_item}>{each_item}</div>) } export default Childlist
这样修改后,不管输入框是否为空,都不会再出现NaN项了~ 你可以根据自己的需求选择方案A或方案B。
内容来源于stack exchange
相关产品推荐
相关产品推荐

