From ba31564d5a061cab685604ad5bb038721d840c91 Mon Sep 17 00:00:00 2001 From: Steven Carter Date: Thu, 21 Nov 2019 00:07:45 -0500 Subject: [PATCH] Removing calls to setState after unmount (#139) Issue #139 was the same issue I was having when resizing a window. I was receiving an error about a possible memory leak since setState was called on an unmounted component. It seems like the `getMatches` call was taking just long enough that the component could be unmounted while it was executing. By using a `_mounted` flag, we can determine if it is safe to call `setState` and bypass it if the component is unmounted. I looked at using an abort signal, but I don't think the `matchMedia` API is robust enough for that currently. --- modules/Media.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/Media.js b/modules/Media.js index 784adf8..f12ee80 100644 --- a/modules/Media.js +++ b/modules/Media.js @@ -28,6 +28,8 @@ class Media extends React.Component { onChange: PropTypes.func }; + _mounted = false; + queries = []; constructor(props) { @@ -98,14 +100,11 @@ class Media extends React.Component { }; updateMatches = () => { - const newMatches = this.getMatches(); + const matches = this.getMatches(); - this.setState( - () => ({ - matches: newMatches - }), - this.onChange - ); + if (this._mounted) { + this.setState({matches}, this.onChange); + } }; initialize() { @@ -132,6 +131,7 @@ class Media extends React.Component { } componentDidMount() { + this._mounted = true; this.initialize(); // If props.defaultMatches has been set, ensure we trigger a two-pass render. // This is useful for SSR with mismatching defaultMatches vs actual matches from window.matchMedia @@ -149,6 +149,7 @@ class Media extends React.Component { } componentWillUnmount() { + this._mounted = false; this.queries.forEach(({ mqListener }) => mqListener.cancel()); }