class组件转函数式组件时相同逻辑出现不同运行表现问题排查
问题修复方案
核心问题原因
- 定时器逻辑错误:你在
else分支创建setTimeout后立刻执行了clearTimeout(t),定时器直接被销毁,永远不会触发回调内的selectItem()调用。你将selectedItem设为null后没有自动后续逻辑,只能手动再次点击才会进入if分支生成新的选中项,这就是需要点击两次的直接原因。 - 你之前遇到的无限循环是因为没有正确管理定时器引用:函数式组件每次重渲染都会生成新的
selectItem函数,没有及时清理的旧定时器会重复触发调用,你通过创建后立刻清理定时器的方式避免了无限循环,但也破坏了原有逻辑。 - 存在冗余变量声明:
if分支内重复声明了同名局部变量selectedItem,属于无效代码,可直接优化。
修复步骤
首先用useRef存储定时器ID,用于统一管理定时器的创建和清理,同时在组件卸载时自动清理避免内存泄漏:
import { useRef, useEffect } from 'react' // 组件内部代码 const timerRef = useRef(null) // 组件卸载时清理残留定时器 useEffect(() => { return () => { if (timerRef.current) clearTimeout(timerRef.current) } }, [])
修改selectItem函数逻辑,调整定时器的清理时机:
const selectItem = () => { // 每次调用先清理旧定时器,避免重复触发 if (timerRef.current) clearTimeout(timerRef.current) if (selectedItem === null) { const newSelectedItem = Math.floor(Math.random() * items.length) console.log(newSelectedItem) setSelectedItem(newSelectedItem) } else { setSelectedItem(null) timerRef.current = setTimeout(() => { selectItem() }, 500) } }
修改后逻辑与原class版本完全一致,既不会出现无限循环,也不需要点击两次触发效果。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

