React项目使用ChartJS图表首屏加载异常、刷新重渲染闪烁问题求助
问题原因分析
- 两个异步接口独立返回,任意一个请求完成更新state都会触发
flatData执行,此时另一个接口还未返回,对应state是初始空值/undefined,处理后的数据异常就会出现undefined展示 - 两个接口先后返回会触发两次
flatData、两次图表渲染,两次渲染的间隙就是你看到的闪烁现象,50个图表的场景下重复渲染还会导致明显的性能损耗
解决方案
1. 加载遮罩与异常展示处理
新增加载状态统一控制渲染时机,加载完成前展示遮罩/骨架屏,避免异常内容暴露:
// 新增加载状态 const [isLoading, setIsLoading] = useState(true) useEffect(() => { const fetchAllData = async () => { setIsLoading(true) try { // 并行请求两个接口,等全部返回再处理 const [monthRes, productRes] = await Promise.all([ http.get("/endpoint1"), http.get("/endpoint2") ]) setEstimatedMonths(monthRes.data.data) setEstimatedProducts(productRes.data.data) } catch (e) { console.log("error", e) } finally { setIsLoading(false) } } fetchAllData() }, [control]) // 渲染层逻辑示例 return ( <div className="chart-container"> {isLoading ? <div className="loading-mask">加载中...</div> : <ChartComponent data={values} />} </div> )
2. 解决图表闪烁重复渲染问题
- 采用上面的
Promise.all统一处理请求,所有数据准备完成后才会触发一次flatData和图表渲染,从根源避免重复渲染 - 新增Chart实例销毁逻辑,避免重复创建实例导致的渲染异常和内存泄漏:
// 提前用useRef存储chart实例 const chartInstance = useRef(null) useLayoutEffect(() => { // 先销毁旧实例 if(chartInstance.current) { chartInstance.current.destroy() } // 再创建新图表 chartInstance.current = chart() return () => { // 组件卸载时销毁实例 chartInstance.current?.destroy() } }, [values])
排查验证方法
- 在
flatData、chart函数中添加日志,确认优化后是否仅触发1次 - 打开浏览器性能面板录制刷新过程,确认图表对应的DOM节点是否仅重绘1次
内容的提问来源于stack exchange,提问作者zhyp
相关产品推荐
相关产品推荐

