Javascript Can';t在未安装的组件上调用setState(或forceUpdate)。这是一个no-op,但它表示应用程序中存在内存泄漏

Javascript Can';t在未安装的组件上调用setState(或forceUpdate)。这是一个no-op,但它表示应用程序中存在内存泄漏,javascript,reactjs,firebase,Javascript,Reactjs,Firebase,为什么我会犯这个错误 警告:无法在未安装的服务器上调用setState(或forceUpdate) 组成部分。这是一个no op,但它表明您的内存中存在内存泄漏 应用若要修复,请取消所有订阅和异步任务 在componentWillUnmount方法中 postAction.js export const getPosts = () => db.ref('posts').once('value'); 组件: constructor(props) { super(props); th

为什么我会犯这个错误

警告:无法在未安装的服务器上调用setState(或forceUpdate) 组成部分。这是一个no op,但它表明您的内存中存在内存泄漏 应用若要修复,请取消所有订阅和异步任务 在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>
  );
}
构造函数(道具){
超级(道具);
this.state={posts:null};
}
componentDidMount(){
getPosts()
。然后(快照=>{
const result=snapshot.val();
this.setState(()=>({posts:result}));
})
.catch(错误=>{
控制台错误(error);
});
}
组件将卸载(){
this.setState({posts:null});
}
render(){
返回(
);
}
删除此

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

从文档:

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


React组件的状态是本地实体。未安装的组件没有状态,不需要这样做。React已经告诉您这是一个
无操作
,这意味着在tech speak中没有操作。这意味着您告诉组件在其已被破坏时执行某些操作

您不应该在componentWillUnmount()中调用setState(),因为该组件永远不会重新呈现。组件实例一旦卸载,将永远不会再次装载


正如其他人提到的,componentWillUnmount中的setState是不必要的,但它不应该导致您看到的错误。相反,可能的罪魁祸首是以下代码:

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

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

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

render() {
  return (
    <div>
      <PostList posts={this.state.posts} />
    </div>
  );
}
由于getPosts()是异步的,所以在解析之前,组件可能已卸载。您没有对此进行检查,因此.then可以在卸载组件后运行

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

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;
}
您可以尝试以下代码:

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

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

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

render() {
  return (
    <div>
      <PostList posts={this.state.posts} />
    </div>
  );
}
构造函数(道具){
超级(道具);
this.state={posts:null};
}
_isMounted=错误;
componentDidMount(){
这个。_isMounted=true;
getPosts()
。然后(快照=>{
const result=snapshot.val();
如果(这个){
this.setState(()=>({posts:result}))
}
})
.catch(错误=>{
控制台错误(error);
});
}
组件将卸载(){
这个。_isMounted=false;
this.setState({posts:null});
}
render(){
返回(
);
}

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

未安装的组件没有状态,无需执行此操作。React已经告诉您这是一个
无操作
您不应该调用
this。在
组件中设置状态
将卸载
。如果你删除了它,警告会消失吗?嘿,你可以在官方网站上阅读这些文档。它说,当组件卸载时,不会进行任何状态更新,因为最终该组件的UI将被销毁EdgetPosts()是异步方法。这是个错误。谢谢大家。谢谢@nicolas towerI不明白为什么这个解决方案如此流行。这只会使代码以静默方式失败(即不显示结果),并消除警告。@milosa组件已卸载的事实意味着父组件决定不再显示结果。因此,在大多数情况下,默示没有结果是预期的行为。如果您的需求不同,您当然可以采用不同的方法。