1
votes

In my react app I am making API call using axios. But, in my console, I got an error "Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method." My code is below

To fix the memory leak, I added _isMounted check and consoled the _ismounted. My app is rendered twice. First-time console prints _isMounted status true and then false (due to componentDidMount) but then the app is rendered second time & _isMounted in the console is printed as true.

app.jsx
export class Test extends Component {
_isMounted = false;
  constructor(props) {
    super(props);
    this.state = {
      apiData: null
    }
  }
  componentDidMount() {
    this._isMounted = true;
    API.callAPI(this.setStateHandler, this._isMounted)
  }
  setStateHandler = (state) => {
    this.setState(state);
  }
 componentWillUnmount() {
    this._isMounted = false
  }
 render() {
  return(...)}

api.js
callAPI = (setStateHandler, _isMounted) => {
    axios.get('/article', {headers: {Authorization: token}})
    .then((response) => {
      if(_isMounted) {
        setStateHandler({ programs: response.data.data.programs });
      }
    })
  }
  1. I would like to fix my memory leak issue. How should I fix that?
  2. Why is my application rendered twice and the second time componentDidUnmount is not called?

I would appreciate the help.

1

1 Answers

0
votes

The _isMounted argument passed in to callAPI will not change when your component is unmounted.

You could instead return the data to the component and check if this._isMounted is still true there instead.

Example

// App.jsx
export class Test extends Component {
  _isMounted = false;
  state = { programs: null };

  componentDidMount() {
    this._isMounted = true;

    API.callAPI().then(data => {
      if (this._isMounted) {
        this.setState({ programs: data.data.programs });
      }
    });
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  render() {
    // ...
  }
}

// api.js
const callAPI = () => {
  return axios
    .get("/article", { headers: { Authorization: token } })
    .then(response => response.data);
};