React函数组件:更新状态的onClick事件处理函数异常问题
问题原因
你遇到的问题根源在于Array.prototype.push()方法的返回值——它不会返回新数组,而是返回数组更新后的长度。第一次点击按钮时,timeList.push(time)给空数组添加一个元素,返回长度1,你把这个数字赋值给newTimeList后更新状态,导致timeList变成了数字类型,后续的length判断自然失效。
修复方法
要正确更新数组状态,必须创建新数组(React状态是不可变的,直接修改原数组不会触发组件重新渲染),以下是两种常用方式:
方式1:展开运算符生成新数组
const handleClick = () => { if (time) { // 展开原数组元素,追加新时间,生成全新数组 const newTimeList = [...timeList, time]; setTimeList(newTimeList); } };
方式2:使用concat方法创建新数组
const handleClick = () => { if (time) { // concat返回拼接后的新数组,不会修改原数组 const newTimeList = timeList.concat(time); setTimeList(newTimeList); } };
更安全的函数式更新写法
如果状态更新依赖前一次的状态值,推荐用函数式更新,避免闭包导致的状态过期问题:
const handleClick = () => { if (time) { setTimeList(prevList => [...prevList, time]); } };
额外小问题修复
除核心bug外,代码还有两处细节问题:
- 列表渲染错误:
showTimeList里的map返回<p>item</p>,会固定渲染字符串"item",而非数组中的时间值,同时需添加key属性:
const timesArr = timeList.map((item, index) => { return <p key={index}>{item}</p>; });
- useEffect无限循环:原代码依赖
time,每次setTime都会触发useEffect重新执行calcTime,形成无限循环。应改为空依赖仅挂载时执行,再通过递归实现持续更新:
useEffect(() => { calcTime(); }, []); // 空依赖,仅组件挂载时执行一次 const calcTime = () => { setTimeout(() => { const today = new Date(); const timeNow = `${today.getHours()}:${today.getMinutes()}:${today.getSeconds()}`; setTime(timeNow); // 递归调用,保持每5秒更新一次时间 calcTime(); }, 5000); };
内容的提问来源于stack exchange,提问作者NewToJS
相关产品推荐
相关产品推荐

