You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用Chart.js 2展示图表时出现内存泄漏错误

React图表组件首次加载内存泄漏/渲染失败问题

我用React + Chart.js实现了一个展示潜在客户(Leads)数量的柱状图组件,代码如下:

import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from "chart.js"
import { Bar } from "react-chartjs-2"

ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)

function Reports() {
  const [graph, setGraph] = useState({})

  const options = {
    responsive: true,
    plugins: {
      legend: {
        position: "top",
      },
      title: {
        display: true,
        text: "Chart.js Bar Chart",
      },
    },
  }

  const handleAllLeadsGenerated = () => {
    axios({
      method: "get",
      url: `${serverUrl}/reports/leads`,
      headers: {
        Authorization: `Bearer ${token}`,
      },
    })
      .then((res) => {
        console.log("response: ", res)
        setGraph({
          labels: res.data.map((row) => {
            return row.firstname
          }),
          datasets: [
            {
              label: "Leads Generation",
              data: res.data.map((row, index) => {
                return parseInt(row.countn)
              }),
              backgroundColor: "rgba(255, 99, 132, 0.5)",
            },
          ],
        })
      })
      .catch((err) => {
        console.log("error: ", err)
      })
  }

  useEffect(() => {
    handleAllLeadsGenerated()
    // eslint-disable-next-line
  }, [])

  return (
    <>
      <div className="content">
        <ToastContainer position="top-right" autoClose={5000} hideProgressBar={false} newestOnTop closeOnClick rtl={false} pauseOnFocusLoss draggable pauseOnHover theme="colored" />
        <Tabs>
          <TabList>
            <Tab>Leads Generation</Tab>
            <Tab>Recuiters Report</Tab>
          </TabList>
          <TabPanel>
            <Row>
              <Col md="12">
                <Card>
                  <CardHeader style={{ display: "flex", alignItems: "center" }}>
                    <CardTitle tag="h4">Leads Info</CardTitle>
                    <Button onClick={handleAllLeadsGenerated}>Reload</Button>
                  </CardHeader>
                  <CardBody>{graph ? <Bar options={options} data={graph} /> : <Spinner animation="border" />}</CardBody>
                </Card>
              </Col>
            </Row>
          </TabPanel>
        </Tabs>
      </div>
    </>
  )
}

export default Reports

问题现象

  • 首次加载页面、刷新页面或从其他页面进入该组件时,出现内存泄漏错误,页面空白无内容渲染
  • 临时缓解方式:注释掉CardBody中的<Bar />组件,编译后再取消注释,图表能正常显示,但上述场景下仍会报错

解决方案

1. 修复初始状态判断逻辑

当前graph初始值为{},而空对象在JS中属于真值,导致graph ? ... : ...的判断永远为真——首次渲染时<Bar />拿到的是没有labels和datasets的空数据,直接触发Chart.js的渲染错误。

把初始状态改为null:

const [graph, setGraph] = useState(null)

2. 取消请求防止内存泄漏

组件卸载时如果请求还未完成,会导致内存泄漏。用axios的CancelToken取消未完成的请求:

useEffect(() => {
  const source = axios.CancelToken.source();
  
  const handleAllLeadsGenerated = () => {
    axios({
      method: "get",
      url: `${serverUrl}/reports/leads`,
      headers: {
        Authorization: `Bearer ${token}`,
      },
      cancelToken: source.token
    })
    .then((res) => {
      setGraph({
        labels: res.data.map(row => row.firstname),
        datasets: [{
          label: "Leads Generation",
          data: res.data.map(row => parseInt(row.countn)),
          backgroundColor: "rgba(255, 99, 132, 0.5)",
        }]
      })
    })
    .catch((err) => {
      if (!axios.isCancel(err)) {
        console.log("error: ", err)
      }
    })
  }

  handleAllLeadsGenerated();

  return () => {
    source.cancel("组件卸载,取消请求");
  };
}, [token, serverUrl])

3. 补全依赖项

移除eslint-disable-next-line注释,将token和serverUrl加入useEffect的依赖数组,避免闭包导致的 stale 数据问题。

4. 可选:添加数据合法性校验

在设置图表数据前,校验接口返回的res.data是否为有效数组,避免空数据导致的渲染异常:

.then((res) => {
  if (Array.isArray(res.data) && res.data.length > 0) {
    setGraph({
      labels: res.data.map(row => row.firstname),
      datasets: [{
        label: "Leads Generation",
        data: res.data.map(row => parseInt(row.countn)),
        backgroundColor: "rgba(255, 99, 132, 0.5)",
      }]
    })
  } else {
    // 处理空数据场景,比如展示空图表或提示
    setGraph({
      labels: [],
      datasets: [{ label: "Leads Generation", data: [] }]
    })
  }
})

内容的提问来源于stack exchange,提问作者PakDragoon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:33:25