【问题标题】:How to cancel all subscriptions and asynchronous task in the componentWillUnmount in React Native?React Native中如何取消componentWillUnmount中的所有订阅和异步任务?
【发布时间】:2019-10-26 15:59:37
【问题描述】:

我在两个屏幕之间导航成功,但它总是在下面显示警告我:

警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。修复,在componentWillUnmount方法中取消所有订阅和异步任务

在警报中(在 AwesomeAlert.js:7)

在 AwesomeAlert 中(在 LoadingDialog.js:7)

在 LoadingDialog 中(在 LoginScreen.js:180)

如何解决?

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    您可以在挂载时设置一个布尔状态标志(isMounted 或类似的),然后在componentWillUnmount 中将其设置为false。在调用引发此警告的函数之前检查此标志。

    【讨论】:

    • 虽然这可行,但isMounted is an antipattern。最好专门清理任务并使用 AbortController
    • 程序点,isMounted() 是一种反模式,使用属性是远离它的建议迁移路径:“只需在 componentDidMount 中将 _isMounted 属性设置为 true,并在 componentWillUnmount 中将其设置为 false,然后使用此变量检查组件的状态"
    【解决方案2】:

    1) 确保您在 componentDidMount拥有任何 event listeners, setTimeouts or setIntervals 并在 componentDidMount 中删除它们强>componentWillUnmount

    监听器、setTimeouts 和 setIntervals 的示例:

    componentDidMount() {
    
      this.myTimer = setTimeout(() => {
        // someCode here
      }, 7000);
    
      AppState.addEventListener('change', this.handleAppStateChange);
    }
    
    
    componentWillUnmount() {
    
       AppState.removeEventListener('change', this.handleAppStateChange);
       clearTimeout(this.myTimer);
    
    }
    

    2) 要取消提取,您有以下选择:

    选项A:使用AbortController

    (在我看来,AbortController 比带有 isMounted 变量的旧解决方案要好得多)

    AbortController 示例:

    import "abortcontroller-polyfill"; // in RN 0.60+ this will probably not be needed anymore
    
    class App extends React.Component {
        constructor() {
            const AbortController = window.AbortController;
            this.controller = new AbortController();
            this.signal = this.controller.signal;
        }
    componentDidMount() {
        const url = "https://myurl.com";
        const signal = this.signal;
    
        fetch(url, { signal })
        .then(res => res.json())
        .then(json => console.log(json))
        .catch(err => {
            // You can catch the error
            // thrown by the polyfill here.
            if (err.name == "AbortError") {
                console.log("Fetch Aborted");
            } else {
               //Catch other errors.
            }
        });
    }
    componentWillUnmount() {
        this.controller.abort();
    }
    /*--Rest of the code.--*/
    

    }

    选项 B:使用Axios 并在componentDidMount 中触发取消

    https://github.com/axios/axios#cancellation

    来源:

    AbortController 代码: https://github.com/facebook/react-native/issues/18115#issuecomment-420766665

    How to cancel a fetch on componentWillUnmount

    https://developer.mozilla.org/en-US/docs/Web/API/AbortController

    【讨论】:

    • 这种方式在我的 setState() 调用 componentDidMount 之前中止承诺,并且我有 emty 状态(不可用)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 2021-01-28
    • 2018-09-26
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多