在reactjs中停止超时?

问题描述 投票:0回答:5

有没有办法可以杀死/(摆脱)reactjs 中的超时?

setTimeout(function() {
//do something
}.bind(this), 3000);

通过某种点击或操作,我希望能够完全停止并结束超时。有没有办法做到这一点?谢谢。

reactjs settimeout
5个回答
30
投票

假设这发生在组件内部,请存储超时 ID,以便稍后可以取消。否则,您需要将 id 存储在以后可以访问的其他地方,例如外部存储对象。

this.timeout = setTimeout(function() {
  // Do something
  this.timeout = null
}.bind(this), 3000)

// ...elsewhere...

if (this.timeout) {
  clearTimeout(this.timeout)
  this.timeout = null
}

您可能还想确保在

componentWillUnmount()
中取消任何挂起的超时:

componentWillUnmount: function() {
  if (this.timeout) {
    clearTimeout(this.timeout)
  }
}

如果您有一些 UI 取决于超时是否挂起,则您需要将 id 存储在适当的组件状态中。


13
投票

由于 React mixins 现已被弃用,这里是一个高阶组件的示例,它包装另一个组件以提供与接受的答案中描述的相同的功能。它巧妙地清理了卸载时剩余的超时,并为子组件提供了一个 API 来通过 props 来管理它。

这使用 ES6 类和 组件组合,这是 2017 年替换 mixin 的推荐方法。

在Timeout.jsx中

import React, { Component } from 'react';

const Timeout = Composition => class _Timeout extends Component {
    constructor(props) {
      super(props);
    }

    componentWillMount () {
      this.timeouts = [];
    }

    setTimeout () {
      this.timeouts.push(setTimeout.apply(null, arguments));
    }

    clearTimeouts () {
      this.timeouts.forEach(clearTimeout);
    }

    componentWillUnmount () {
      this.clearTimeouts();
    }

    render () {
      const { timeouts, setTimeout, clearTimeouts } = this;

      return <Composition 
        timeouts={timeouts} 
        setTimeout={setTimeout} 
        clearTimeouts={clearTimeouts} 
        { ...this.props } />
    }
}

export default Timeout;

在MyComponent.jsx中

import React, { Component } from 'react';
import Timeout from './Timeout';    

class MyComponent extends Component {
  constructor(props) {
    super(props)
  }

  componentDidMount () {
    // You can access methods of Timeout as they
    // were passed down as props.
    this.props.setTimeout(() => {
      console.log("Hey! I'm timing out!")
    }, 1000)
  }

  render () {
    return <span>Hello, world!</span>
  }
}

// Pass your component to Timeout to create the magic.
export default Timeout(MyComponent);

12
投票

你应该使用mixin:

// file: mixins/settimeout.js:

var SetTimeoutMixin = {
    componentWillMount: function() {
        this.timeouts = [];
    },
    setTimeout: function() {
        this.timeouts.push(setTimeout.apply(null, arguments));
    },

    clearTimeouts: function() {
        this.timeouts.forEach(clearTimeout);
    },

    componentWillUnmount: function() {
        this.clearTimeouts();
    }
};

export default SetTimeoutMixin;

...在你的组件中:

// sampleComponent.js:
import SetTimeoutMixin from 'mixins/settimeout'; 

var SampleComponent = React.createClass({

    //mixins:
    mixins: [SetTimeoutMixin],

    // sample usage
    componentWillReceiveProps: function(newProps) {
        if (newProps.myValue != this.props.myValue) {
            this.clearTimeouts();
            this.setTimeout(function(){ console.log('do something'); }, 2000);
        }
    },
}

export default SampleComponent;

更多信息:https://facebook.github.io/react/docs/reusable-components.html


2
投票

我仅使用 Javascript 在我的 React 应用程序中停止了 setTimeout:

(我的用例是仅在 3 秒内没有击键后才自动保存)

timeout;

handleUpdate(input:any) {
    this.setState({ title: input.value }, () => {

        clearTimeout(this.timeout);
        this.timeout = setTimeout(() => this.saveChanges(), 3000);

    });
}

0
投票

2023 经过测试并投入生产。在这个帖子没有给我提供答案之后,我就是这样做的。

const MyComponent: React.FC<Props> = ({
  children,
  className = '',
}) => { 
  const timeoutRef = useRef<NodeJS.Timeout | null>(null)
  const [loaded, setLoaded] = useState(false)

  useEffect(() => {
    timeoutRef.current = setTimeout(
      () => setLoaded(true),
      10000
    )
    return () => {
      timeoutRef.current && clearTimeout(timeoutRef.current)
    }
    
  }, []) //eslint-disable-line

  const handleCancelTimeout = () => {
    timeoutRef.current && clearTimeout(timeoutRef.current)
  }

}
© www.soinside.com 2019 - 2024. All rights reserved.