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

React类组件中“无法在已卸载组件上执行状态更新”错误的求助

Fixing "Can't perform a React state update on an unmounted component" in your React Class Component

I've run into this exact issue before—super frustrating when you can see your data is coming through but that warning won't go away! Let's break down why this is happening and how to fix it.

Why this error happens

The warning pops up because your axios request finishes after the component has already unmounted. When you call this.setState() in the .then() callback, React tries to update the state of a component that no longer exists in the DOM. This is not only useless but can lead to memory leaks over time.


Axios has built-in support for canceling requests using CancelToken. This stops the request from completing entirely once the component is unmounted, so we never try to update state at all.

Here's how to modify your component:

import axios from 'axios';
import { Component } from 'react';
import { Line } from 'react-chartjs-2'; // Assuming you're using react-chartjs-2

class BarChart extends Component { 
  constructor(){ 
    super(); 
    this.state = { chartData:{} };
    // Create a cancel token source
    this.cancelTokenSource = axios.CancelToken.source();
  } 

  componentDidMount() { 
    this.getChartData(); 
  } 

  componentWillUnmount() {
    // Cancel the request when the component unmounts
    this.cancelTokenSource.cancel('Component unmounted, cancelling pending request');
  }

  getChartData() { 
    axios.get("http://localhost:5001/inventory/clusterscount", {
      // Attach the cancel token to the request
      cancelToken: this.cancelTokenSource.token
    }).then(res => { 
      const myresponse = res.data; 
      let countcluster = []; 
      let listregion = []; 
      for (const dataobj of myresponse){ 
        countcluster.push(parseInt(dataobj.clusterscount)); 
        listregion.push(dataobj.region); 
      } 
      this.setState({ 
        chartData: { 
          labels:listregion, 
          datasets: [ 
            { 
              label: "level of thiccness", 
              data: countcluster, 
              backgroundColor: ["rgba(75, 192, 192, 0.6)"], 
              borderWidth: 4 
            } 
          ] 
        } 
      }); 
    }).catch(error => {
      // Ignore cancellation errors so we don't log unnecessary warnings
      if (axios.isCancel(error)) {
        console.log('Request cancelled:', error.message);
      } else {
        // Handle other errors normally
        console.error('Error fetching data:', error);
      }
    }); 
  } 

  render(){ 
    return ( 
      <div className="App"> 
        <h1>Dankmemes</h1> 
        <div> 
          <Line data={this.state.chartData} options={{ 
            responsive: true, 
            title: { 
              text: "THICCNESS SCALE", 
              display: true 
            }, 
            scales: { 
              yAxes: [ 
                { 
                  ticks: { 
                    autoSkip: true, 
                    maxTicksLimit: 10, 
                    beginAtZero: true 
                  }, 
                  gridLines: { 
                    display: false 
                  } 
                } 
              ], 
              xAxes: [ 
                { 
                  gridLines: { 
                    display: false 
                  } 
                } 
              ] 
            } 
          }} /> 
        </div> 
      </div> 
    ); 
  } 
} 

export default BarChart;

Solution 2: Track component mount status with a flag

If you prefer a simpler approach (or can't cancel the request for some reason), you can add a flag to track whether the component is still mounted before calling setState.

class BarChart extends Component { 
  constructor(){ 
    super(); 
    this.state = { chartData:{} };
    // Initialize the mount flag
    this._isMounted = false;
  } 

  componentDidMount() { 
    this._isMounted = true; // Set to true when component mounts
    this.getChartData(); 
  } 

  componentWillUnmount() {
    this._isMounted = false; // Set to false when component unmounts
  }

  getChartData() { 
    axios.get("http://localhost:5001/inventory/clusterscount").then(res => { 
      const myresponse = res.data; 
      let countcluster = []; 
      let listregion = []; 
      for (const dataobj of myresponse){ 
        countcluster.push(parseInt(dataobj.clusterscount)); 
        listregion.push(dataobj.region); 
      } 
      // Only update state if the component is still mounted
      if (this._isMounted) {
        this.setState({ 
          chartData: { 
            labels:listregion, 
            datasets: [ 
              { 
                label: "level of thiccness", 
                data: countcluster, 
                backgroundColor: ["rgba(75, 192, 192, 0.6)"], 
                borderWidth: 4 
              } 
            ] 
          } 
        }); 
      }
    }); 
  } 

  // Render method remains the same as your original code
} 

export default BarChart;

Which solution should you use?

  • Solution 1 (CancelToken) is better because it stops the network request entirely, saving bandwidth and avoiding unnecessary processing. This is the cleanest approach.
  • Solution 2 (Mount flag) is a quick fix but doesn't cancel the request—the request will still complete, we just skip updating the state. Use this if you need a simpler change and don't mind the extra network traffic.

Either way, both will eliminate that annoying warning and prevent potential memory leaks!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:22:29