【问题标题】: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.

【问题讨论】:

    标签: javascript reactjs


    【解决方案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) 您必须知道它对这些值是无效的。但同样,是的,风格真的...... :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2012-03-14
    • 2018-04-26
    • 1970-01-01
    相关资源
    最近更新 更多