无法在已卸载的组件上调用setState(或forceUpdate)。这是空操作,但表示您的应用程序内存泄漏

时间:2018-07-09 13:30:56

标签: javascript reactjs firebase

为什么会出现此错误?

  

警告:无法在已卸载的设备上调用setState(或forceUpdate)   零件。这是空操作,但表示您的内存泄漏   应用。要修复,请取消所有订阅和异步任务   在componentWillUnmount方法中。

postAction.js

export const getPosts = () => db.ref('posts').once('value');

组件:

constructor(props) {
  super(props);
  this.state = { posts: null };
}

componentDidMount() {
  getPosts()
    .then(snapshot => {
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

componentWillUnmount() {
  this.setState({ posts: null });
}

render() {
  return (
    <div>
      <PostList posts={this.state.posts} />
    </div>
  );
}

4 个答案:

答案 0 :(得分:4)

就像其他人提到的那样,componentWillUnmount中的setState是不必要的,但是它不会引起您看到的错误。相反,可能的原因是此代码:

componentDidMount() {
  getPosts()
    .then(snapshot => {
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

由于getPosts()是异步的,因此在解析之前,可能已卸载了该组件。您无需进行检查,因此.then可以在卸载组件后最终运行。

要处理此问题,可以在willUnmount中设置一个标志,然后在.then中检查该标志:

componentDidMount() {
  getPosts()
    .then(snapshot => {
      if (this.isUnmounted) {
        return;
      }
      const result = snapshot.val();
      this.setState(() => ({ posts: result }));
    })
    .catch(error => {
      console.error(error);
    });
}

componentWillUnmount() {
  this.isUnmounted = true;
}

答案 1 :(得分:0)

删除此

componentWillUnmount() {
  this.setState({ posts: null });
}

没用

来自文档:

  

您不应在componentWillUnmount()中调用setState(),因为   组件将永远不会被重新渲染。一旦组件实例是   卸载后,将不再安装。

https://reactjs.org/docs/react-component.html#componentwillunmount

答案 2 :(得分:0)

反应组件的状态是本地实体。卸载的组件没有状态,无需这样做。 React已经告诉您这是no-op,这意味着在技术方面无法操作。这意味着您要告诉组件在其已被破坏时执行某些操作。

https://reactjs.org/docs/react-component.html#componentwillunmount

  

您不应在componentWillUnmount()中调用setState(),因为永远不会重新渲染该组件。卸载组件实例后,将永远不会再次安装它。

答案 3 :(得分:0)

您可以尝试以下代码:

.stackarea

通过使用_isMounted,仅在安装了组件时才调用setState。答案只是在设置状态之前进行检查以查看是否已安装组件。