无法在socket.io回调React.js中调用setState

时间:2019-05-03 12:15:00

标签: javascript reactjs socket.io react-router react-state

我面临以下问题:

在处理状态的React组件中,有一个与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方法。而且该组件未卸载。

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

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

父组件具有以下路由(从概念上讲):

 <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()内console.log消息,我看不到它正在卸载。

任何想法将不胜感激!

随时提问。

1 个答案:

答案 0 :(得分:4)

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/