无法在 socket.io 回调 React.js 中调用 setState
Can't call setState inside socket.io callback React.js
我面临以下问题:
在一个处理状态的 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 存在于两个组件中)。问题是这个组件很大,因为它是一个容器,将所有状态移动到父级并使用道具会导致大量重写..
这让我意识到应用程序的反应路线可能存在一些问题。
父组件有以下路由(概念上):
<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.
的最新版本
是否有可能以某种方式对组件的第一个实例 "freezes" 作出反应,然后 url 发生变化,我无法再更新状态?如果我 console.log 里面有一条消息 componentWillUnmount()
我看不到它正在卸载。
任何想法将不胜感激!
欢迎提问。
React 告诉您必须删除 componentWillUnmount:
中的侦听器
componentWillUnmount() {
socket.off('some event');
}
这是因为:
- 如果您在 componentDidMount 中添加侦听器,您最终会得到多个侦听器
- 当组件被卸载时(在路由更改时)"this" 并且它的上下文绑定不再有意义,但是回调无论如何都会尝试在每次事件发生时设置状态
形成反应文档:
componentWillUnmount() is invoked immediately before a component is
unmounted and destroyed. Perform any necessary cleanup in this method,
such as invalidating timers, canceling network requests, or cleaning
up any subscriptions that were created in componentDidMount().
参考:https://reactjs.org/docs/react-component.html?utm_source=caibaojian.com#componentwillunmount
另一个更好地理解问题的资源:
https://advancedweb.hu/2016/01/05/global-listener-patterns-in-react/
我面临以下问题:
在一个处理状态的 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 存在于两个组件中)。问题是这个组件很大,因为它是一个容器,将所有状态移动到父级并使用道具会导致大量重写..
这让我意识到应用程序的反应路线可能存在一些问题。
父组件有以下路由(概念上):
<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.
是否有可能以某种方式对组件的第一个实例 "freezes" 作出反应,然后 url 发生变化,我无法再更新状态?如果我 console.log 里面有一条消息 componentWillUnmount()
我看不到它正在卸载。
任何想法将不胜感激!
欢迎提问。
React 告诉您必须删除 componentWillUnmount:
中的侦听器componentWillUnmount() {
socket.off('some event');
}
这是因为:
- 如果您在 componentDidMount 中添加侦听器,您最终会得到多个侦听器
- 当组件被卸载时(在路由更改时)"this" 并且它的上下文绑定不再有意义,但是回调无论如何都会尝试在每次事件发生时设置状态
形成反应文档:
componentWillUnmount() is invoked immediately before a component is unmounted and destroyed. Perform any necessary cleanup in this method, such as invalidating timers, canceling network requests, or cleaning up any subscriptions that were created in componentDidMount().
参考:https://reactjs.org/docs/react-component.html?utm_source=caibaojian.com#componentwillunmount
另一个更好地理解问题的资源:
https://advancedweb.hu/2016/01/05/global-listener-patterns-in-react/