React类组件中“无法在已卸载组件上执行状态更新”错误的求助
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.
Solution 1: Cancel the Axios request when the component unmounts (recommended)
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

