material-components-web-react: Can't perform a React state update on an unmounted component

Seeing this error when I hide a div that contains many ChipSet components.

index.js:1452 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.
    in RippledComponent
    in div
    in ChipSet

It seems to happen right before execution of this line:

https://github.com/material-components/material-components-web-react/blob/a468f024df300c535d220f9bbc493e5c67af77d5/packages/chips/Chip.js#L74

I see there is no “mounted” check prior to this setState call, maybe this could be the source of error.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 17 (2 by maintainers)

Most upvoted comments

Fix it with this technique.

Look where I added _isMounted and follow the same in you code

class Page extends Component {
  _isMounted = false;

  state = {
    isLoading: true
  }

  componentDidMount() {
    this._isMounted = true;
  
    callAPI_or_DB(...).then(result => {
      if (this._isMounted) {
        this.setState({isLoading: false})
      }
    });
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  render() {
    return (
      <div>Whatever</div>
    );
  }
}

export default Page;

@mohokh67 What about solution for a functional component?

For functional components you can use a custom hook:

import { useEffect, useRef } from "react";

const useIsMounted = () => {
  const isMounted = useRef(false);
  useEffect(() => {
    isMounted.current = true;
    return () => (isMounted.current = false);
  }, []);
  return isMounted;
};

and then use it in your component:

const MyComp = () => {
  const isMounted = useIsMounted();

  useEffect(() => {
    if (isMounted.current) {
      // update your state here
    }
  }, [isMounted]);

  /// ...
};

PS: This might not be worth while.

@5ervant you can use useRef for check if the component still mounted

example

Try https://github.com/iShawnWang/withUnmounted package as an elegant solution

I have met this problem in a situation where the keys were massed up. So it might be coming from above the component itself. In my case the mistake was caused by how I have been generating the keys:

<ul>
{collection.map(o => <li key={JSON.stringify(o)}> {o.title} </li>)}
</ul>

That causes a memory leak as React can’t notice some elements must be removed or created as the key changes on any other change in the collection element. My conclusion is that key should be unique during the life cycle so the state mechanism can rely on it.