Javascript 有没有办法检查反应组件是否已卸载?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39767482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to check if the react component is unmounted?
提问by Dharini S
I have a usecase where i need to unmount my react component. But in some cases, the particular react component is unmounted by a different function. Hence, I need to check if the component is mounted before unmounting it.
我有一个需要卸载 React 组件的用例。但在某些情况下,特定的 react 组件会被不同的函数卸载。因此,我需要在卸载之前检查该组件是否已安装。
回答by Shubham Khatri
Since isMounted()
is being officially deprecated, you can do this in your component:
由于isMounted()
已被正式弃用,您可以在组件中执行此操作:
componentDidMount() {
this._ismounted = true;
}
componentWillUnmount() {
this._ismounted = false;
}
This pattern of maintaining your own state
variable is detailed in the ReactJS documentation: isMounted is an Antipattern.
这种维护自己state
变量的模式在 ReactJS 文档中有详细说明:isMounted is an Antipattern。
回答by Nicola Pedretti
I think that Shubham answer is a workaround suggested by react for people that need to transition their code to stop using the isMounted
anti-pattern.
我认为 Shubham 的答案是 react 为需要转换代码以停止使用isMounted
反模式的人建议的解决方法。
This is not necessarily bad, but It's worth listing the real solutions to this problem.
这不一定是坏事,但值得列出这个问题的真正解决方案。
The article linked by Shubhamoffers 2 suggestions to avoid this anti pattern. The one you need depends on why you are calling setState when the component is unmounted.
Shubham 链接的文章提供了 2 个避免这种反模式的建议。您需要的取决于您在卸载组件时调用 setState 的原因。
if you are using a Flux store in your component, you must unsubscribe in componentWillUnmount
如果您在组件中使用 Flux 存储,则必须在 componentWillUnmount 中取消订阅
class MyComponent extends React.Component {
componentDidMount() {
mydatastore.subscribe(this);
}
render() {
...
}
componentWillUnmount() {
mydatastore.unsubscribe(this);
}
}
If you use ES6 promises, you may need to wrap your promise in order to make it cancelable.
如果您使用 ES6 承诺,您可能需要包装您的承诺以使其可取消。
const cancelablePromise = makeCancelable(
new Promise(r => component.setState({...}}))
);
cancelablePromise
.promise
.then(() => console.log('resolved'))
.catch((reason) => console.log('isCanceled', reason.isCanceled));
cancelablePromise.cancel(); // Cancel the promise
Read more about makeCancelable
in the linked article.
makeCancelable
在链接的文章中阅读更多信息。
In conclusion, do not try to patch this issue by setting variables and checking if the component is mounted, go to the root of the problem. Please comment with other common cases if you can come up with any.
总之,不要试图通过设置变量和检查组件是否已安装来修补此问题,请转到问题的根源。如果您能提出任何其他常见案例,请发表评论。
回答by Tarun Gehlaut
Another solution would be using Refs. If you are using React 16.3+, make a ref to your top level item in the render function.
另一种解决方案是使用Refs。如果您使用的是 React 16.3+,请在渲染函数中引用您的顶级项目。
Then simply check if ref.current is null or not.
然后简单地检查 ref.current 是否为空。
Example:
例子:
class MyClass extends React.Component {
constructor(props) {
super(props);
this.elementRef = React.createRef();
}
checkIfMounted() {
return this.elementRef.current != null;
}
render() {
return (
<div ref={this.elementRef} />
);
}
}
回答by melloc
I got here because I was looking for a way to stop polling
the API.
我来到这里是因为我正在寻找一种方法来停止polling
API。
The react docsdoes cover the websocket
case, but not the polling one.
该反应文档不覆盖websocket
的情况下,但不是轮询之一。
The way I worked around it
我解决它的方式
// React component
React.createClass({
poll () {
if (this.unmounted) {
return
}
// otherwise, call the api
}
componentWillUnmount () {
this.unmounted = true
}
})
it works. Hope it helps
有用。希望能帮助到你
Please, let me know if you guys know any failing test case for this =]
请让我知道你们是否知道任何失败的测试用例 =]
回答by GWorking
Using @DerekSoike answer, however in my case using useState
to control the mounted state didn't work since the state resurrected when it didn't have to
使用@DerekSoike 回答,但是在我的情况下,useState
用于控制挂载状态不起作用,因为状态在不需要时复活了
What worked for me was using a single variable
对我有用的是使用单个变量
myFunct
was called in a setTimeout
, and my guess is that when the same component initialized the hook in another page it resurrected the state causing the memory leak to appear again
myFunct
在 a 中被调用setTimeout
,我的猜测是,当同一个组件在另一个页面中初始化钩子时,它会恢复导致内存泄漏再次出现的状态
So this didn't work for me
所以这对我不起作用
const [isMounted, setIsMounted] = useState(false)
useEffect(() => {
setIsMounted(true)
return () => setIsMounted(false)
}, [])
const myFunct = () => {
console.log(isMounted) // not always false
if (!isMounted) return
// change a state
}
And this did work for me
这对我有用
let stillMounted = { value: false }
useEffect(() => {
stillMounted.value = true
return () => (stillMounted.value = false)
}, [])
const myFunct = () => {
if (!stillMounted.value) return
// change a state
}
回答by Derek Soike
If you're using hooks:
如果您使用钩子:
function MyComponent(props: Props) {
const [isMounted, setIsMounted] = useState<boolean>(false);
useEffect(() => {
setIsMounted(true);
}, []);
useEffect(() => {
return () => {
setIsMounted(false);
}
}, []);
return (...);
}
export default MyComponent;
回答by Sajera Cool
The same idea but enother implementation
相同的想法,但另一种实现
/**
* component with async action within
*
* @public
*/
class MyComponent extends Component {
constructor ( ...args ) {
// do not forget about super =)
super(...args);
// NOTE correct store "setState"
let originSetState = this.setState.bind(this);
// NOTE override
this.setState = ( ...args ) => !this.isUnmounted&&originSetState(...args);
}
/**
* no necessary setup flag on component mount
* @public
*/
componentWillUnmount() {
// NOTE setup flag
this.isUnmounted = true;
}
/**
*
* @public
*/
myCustomAsyncAction () {
// ... code
this.setState({any: 'data'}); // do not care about component status
// ... code
}
render () { /* ... */ }
}
回答by Danny Michaeli
You can use:
您可以使用:
myComponent.updater.isMounted(myComponent)
"myComponent" is instance of your react component. this will return 'true' if component is mounted and 'false' if its not..
“myComponent”是你的反应组件的实例。如果组件已安装,则返回“true”,如果未安装,则返回“false”。
- This is not supportedway to do it. you better unsubscribe any async/events on componentWillUnmount.
- 这不是支持的方式。您最好取消订阅componentWillUnmount上的任何异步/事件。
回答by Leonardo Orozco
i found that the component will be unmounted, generate fill this var
我发现组件将被卸载,生成填充这个变量
if(!this._calledComponentWillUnmount)this.setState({vars});