如何为导出文件按钮实现基于setTimeout的分阶段加载提示功能
现有代码的核心问题
- 仅用布尔类型的
loading状态无法存储多套提示文案,没有对应状态驱动视图更新文案 - 定时器延迟时间不符合需求:需求为0秒/10秒/20秒三个切换节点,你的代码设置的是0ms/2000ms/3000ms
- 定时器回调中仅引用了
greet1/greet2/greet3函数,既没有执行函数也没有触发状态更新,视图不会发生任何变化 setLoading是异步更新逻辑,刚执行setLoading(true)就判断if(loading),此时拿到的还是更新前的false值,这部分判断逻辑永远不会触发- 没有做定时器清理逻辑,组件提前卸载时会触发内存泄漏告警
修正后实现代码
import { useState, useRef, useEffect } from 'react'; function ExportButton() { // 控制加载状态 const [loading, setLoading] = useState(false); // 存储动态提示文案 const [exportTip, setExportTip] = useState(''); // 存储定时器ID,用于后续清理 const timer10sRef = useRef(null); const timer20sRef = useRef(null); const handleExport = () => { // 初始化加载状态与初始提示文案 setLoading(true); setExportTip('please wait'); // 10秒后切换提示 timer10sRef.current = setTimeout(() => { setExportTip('loading...'); }, 10000); // 20秒后切换提示 timer20sRef.current = setTimeout(() => { setExportTip('sorry, please wait'); }, 20000); // 此处补充你的实际导出接口请求逻辑,导出完成后重置状态 // 示例: // fetchExportFile().then(res => { // downloadFile(res) // }).finally(() => { // // 清理未执行的定时器 // clearTimeout(timer10sRef.current) // clearTimeout(timer20sRef.current) // // 重置状态 // setLoading(false) // setExportTip('') // }) } // 组件卸载时清理定时器,避免内存泄漏 useEffect(() => { return () => { clearTimeout(timer10sRef.current); clearTimeout(timer20sRef.current); } }, []) // 按钮渲染 return ( <button onClick={handleExport} disabled={loading}> {loading ? exportTip : '导出文件'} </button> ) }
关键调整说明
- 新增
exportTip状态变量存储动态提示文案,状态更新会自动触发视图重渲染 - 按需求调整了定时器延迟时间为10000ms、20000ms,初始提示文案直接在触发导出时赋值,不需要额外的0秒定时器
- 定时器回调中直接调用
setExportTip更新状态,实现文案切换 - 用
useRef存储定时器ID,在导出完成、组件卸载两个场景都做了定时器清理,避免内存泄漏和无效状态更新 - 移除了无效的
if(loading)判断,触发导出时直接执行初始化逻辑
内容的提问来源于stack exchange,提问作者tinyVariant
相关产品推荐
相关产品推荐

