首页
/ G2Plot 图表重复渲染问题解析与解决方案

G2Plot 图表重复渲染问题解析与解决方案

2025-06-30 01:16:20作者:裘晴惠Vivianne

问题现象

在使用 G2Plot 进行数据可视化开发时,开发者可能会遇到一个奇怪的现象:按照官方文档示例编写的代码,在页面上却意外地渲染出了两个相同的图表。这种情况通常发生在 React 18 环境下,表现为同一个图表组件被渲染了两次。

问题根源

这个问题的根本原因与 React 18 引入的严格模式(Strict Mode)有关。在严格模式下,React 会故意对组件进行双重渲染,以帮助开发者发现潜在的问题。这种机制会导致以下情况:

  1. 组件生命周期函数会被调用两次
  2. 副作用(Effects)会执行两次
  3. 图表初始化逻辑也会执行两次

G2Plot 的图表实例在每次渲染时都会创建新的 DOM 元素和图表实例,如果组件被渲染两次,就会产生两个图表实例。

解决方案

针对这个问题,开发者可以采取以下几种解决方案:

方案一:禁用严格模式

在 React 18 项目中,可以修改入口文件(index.js 或 main.js),移除 <React.StrictMode> 包裹:

// 修改前
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// 修改后
root.render(<App />);

方案二:使用 useRef 控制图表实例

更推荐的做法是使用 React 的 useRef 来管理图表实例,确保即使组件多次渲染,也只会创建一个图表实例:

import React, { useEffect, useRef } from 'react';
import { Line } from '@antv/g2plot';

const LineChart = () => {
  const containerRef = useRef(null);
  const chartRef = useRef(null);

  useEffect(() => {
    if (!chartRef.current && containerRef.current) {
      const line = new Line(containerRef.current, {
        // 图表配置
      });
      line.render();
      chartRef.current = line;
    }

    return () => {
      if (chartRef.current) {
        chartRef.current.destroy();
        chartRef.current = null;
      }
    };
  }, []);

  return <div ref={containerRef} />;
};

方案三:使用 React 17 版本

如果项目允许,也可以考虑降级到 React 17 版本,该版本默认不启用严格模式的双重渲染机制。

最佳实践建议

  1. 在开发环境中保留严格模式,它可以帮助发现潜在问题
  2. 使用 useRef 来管理图表实例,这是最健壮的解决方案
  3. 确保在组件卸载时正确销毁图表实例,避免内存泄漏
  4. 对于复杂的可视化场景,考虑将图表组件封装为独立的、受控的组件

总结

G2Plot 图表重复渲染问题本质上是 React 18 严格模式与图表库初始化逻辑的交互问题。通过理解 React 的渲染机制和合理使用 useRef,开发者可以轻松解决这个问题,同时保持代码的健壮性和可维护性。

登录后查看全文
热门项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
22
6
docsdocs
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
161
2.05 K
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
8
0
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
146
191
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Java
60
16
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
198
279
apintoapinto
基于golang开发的网关。具有各种插件,可以自行扩展,即插即用。此外,它可以快速帮助企业管理API服务,提高API服务的稳定性和安全性。
Go
22
0
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
949
556
ShopXO开源商城ShopXO开源商城
🔥🔥🔥ShopXO企业级免费开源商城系统,可视化DIY拖拽装修、包含PC、H5、多端小程序(微信+支付宝+百度+头条&抖音+QQ+快手)、APP、多仓库、多商户、多门店、IM客服、进销存,遵循MIT开源协议发布、基于ThinkPHP8框架研发
JavaScript
96
15
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
346
1.33 K