我如何在反应中取消订阅

Posted

技术标签:

【中文标题】我如何在反应中取消订阅【英文标题】:how can I cancel subscriptions in react 【发布时间】:2021-03-03 22:41:44 【问题描述】:

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

我尝试使用 componentWillUnmount 取消订阅,但警告仍然存在。下面是我的代码。

    constructor(props) 
        super(props);
        const idxStart = 0;
        this.state = 
            current: idxStart,
            prev: this.getPrevIndex(idxStart),
            next: this.getNextIndex(idxStart),
            Text: Text
        ;
        // To disable autoplay, change to false 
        this.autoPlay = true;
    

    getPrevIndex = (idx) => 
        if (idx <= 0) 
            return pics.length - 1;
        
        return idx - 1;
    

    getNextIndex = (idx) => 
        if (idx >= pics.length - 1) 
            return 0;
        
        return idx + 1;
    

    setIndexes = (idx, dir) => 
        this.setState(
            current: idx,
            prev: this.getPrevIndex(idx),
            next: this.getNextIndex(idx),
            dir
        );
    

    transitionSlide = (direction) => 
        if (this.moving) return;
        // start animation
        this.setState(
            dir: direction,
            move: true
        );
        this.moving = true;

        //stop animation
        setTimeout(() => 
            this.setState(
                move: false
            );
            if (direction === 'next') 
                this.setIndexes(this.getNextIndex(this.state.current), 'next');
             else 
                this.setIndexes(this.getPrevIndex(this.state.current), 'prev');
            
            this.moving = false;
        , 500);

    

    componentDidMount() 
        if (this.autoPlay) 
            setInterval(this.handleNext, 6000);
        
    

    componentWillUnmount() 
        this.autoplay === false
        clearInterval(setInterval(this.handleNext, 6000));
        clearTimeout(setTimeout(() => 
            this.setState(
                move: false
            );
            if (direction === 'next') 
                this.setIndexes(this.getNextIndex(this.state.current), 'next');
             else 
                this.setIndexes(this.getPrevIndex(this.state.current), 'prev');
            
        , 500))
    

    handlePrev = () => 
        this.transitionSlide('prev');
    

    handleNext = () => 
        this.transitionSlide('next');
    ```

I have tried to fix this perhaps there is something I am not doing right.

【问题讨论】:

【参考方案1】:

clearInterval(setInterval(this.handleNext, 6000)); 安排一个间隔计时器并立即取消它,让您的间隔计时器仍在运行。

你需要做的是记住你在componentDidMount中从setInterval获得的计时器句柄,可能是一个实例属性,并使用它:

componentDidMount() 
    if (this.autoPlay) 
        this.intervalHandle = setInterval(this.handleNext, 6000);
    


componentWillUnmount() 
    if (this.intervalHandle) 
        clearInterval(this.intervalHandle);
        this.intervalHandle = 0; // Not strictly necessary, but I like to do
                                 // this so I know looking at the handle whether
                                 // I've cancelled it. (The value from
                                 // `setInterval` will never be 0.)
    
    // ...

【讨论】:

我更喜欢将null 用于不活动的间隔/计时器句柄,或者只是使用delete。将其设置为 0 需要开发人员了解此实现细节,而 null 或 delete 将传达句柄未激活 (IMO) @r3wt - 当然,无论你喜欢什么。 null 的实现细节并不比 0 少;在这两种情况下,您都必须知道 A) setInterval 永远不会返回它,如果您这样做 clearInterval 盲目(就像某些人一样) B) 您必须知道它对这些值是无效的。但同样,是的,风格真的...... :-)

以上是关于我如何在反应中取消订阅的主要内容,如果未能解决你的问题,请参考以下文章

如何获取自动续订订阅的状态,主要是在沙盒模式下取消?

无法在我的反应本机应用程序中清理订阅

如何使用钩子清理 componentDidUpdate 中的异步函数

如何在 RxSwift 中取消订阅 Observable?

如何在模拟中验证事件已被取消订阅

在电子邮件标题中列出取消订阅。如何?