5

我面临以下问题:

在处理状态的反应组件内部,有一个与 socket.io 的 websocket 连接。每当我收到一些事件时,我应该做一些操作并更新组件的状态。例子:

socket.on('some event', () => {
 this.aMethod() // this method calls setState()
})

问题是出现以下消息:

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.

但我没有在任何地方使用componentWillUnmount方法。并且该组件未卸载。

如果我替换aMethodwiththis.props.aMethod()并更新将起作用的父组件的状态( aMethod 存在于两个组件中)。问题是这个组件很大,因为它是一个容器,将所有状态移动到父级并使用道具会导致大量重写..

这让我想到应用程序的反应路线可能存在一些问题。

父组件具有以下路线(概念上):

 <Switch>

          <Route exact path={'/user/:id'} render={(props) => <User />} />
          <Route exact path={'/users'} render={(props) => <User />} />

  </Switch>

我使用render而不是component因为我需要将一些方法作为道具传递。React 和 react-router-dom 是 16.x 和 5.0.0 的最新版本。

是否有可能以某种方式“冻结”组件的第一个实例,然后 url 发生变化,我无法再更新状态?如果我在控制台中记录一条消息,componentWillUnmount()我看不到它正在卸载。

任何想法将不胜感激!

随意问的问题。

4

1 回答 1

7

React 告诉你必须删除 componentWillUnmount 中的监听器:

componentWillUnmount() {
 socket.off('some event');
}

这是因为:

  • 如果你在 componentDidMount 中添加监听器,你最终会得到多个监听器
  • 当组件被卸载(在路由更改时)“this”并且它的上下文绑定不再有意义,但回调无论如何都会尝试在每次事件发生时设置状态

形成反应文档:

在卸载和销毁组件之前立即调用 componentWillUnmount()。在此方法中执行任何必要的清理,例如使计时器无效、取消网络请求或清理 在 componentDidMount() 中创建的任何订阅。

参考:https ://reactjs.org/docs/react-component.html?utm_source=caibaojian.com#componentwillunmount

另一个更好地理解这个问题的资源:

https://advancedweb.hu/2016/01/05/global-listener-patterns-in-react/

于 2019-05-03T12:27:47.820 回答