setInterval in a React app

前端 未结 7 521
天涯浪人
天涯浪人 2020-11-30 20:46

I\'m still fairly new at React, but I\'ve been grinding along slowly and I\'ve encountered something I\'m stuck on.

I am trying to build a \"timer\" component in Re

相关标签:
7条回答
  • 2020-11-30 21:15

    If anyone is looking for a React Hook approach to implementing setInterval. Dan Abramov talked about it on his blog. Check it out if you want a good read about the subject including a Class approach. Basically the code is a custom Hook that turns setInterval as declarative.

    function useInterval(callback, delay) {
      const savedCallback = useRef();
    
      // Remember the latest callback.
      useEffect(() => {
        savedCallback.current = callback;
      }, [callback]);
    
      // Set up the interval.
      useEffect(() => {
        function tick() {
          savedCallback.current();
        }
        if (delay !== null) {
          let id = setInterval(tick, delay);
          return () => clearInterval(id);
        }
      }, [delay]);
    }
    

    Also posting the CodeSandbox link for convenience: https://codesandbox.io/s/105x531vkq

    0 讨论(0)
  • 2020-11-30 21:19

    Updated 10-second countdown using class Clock extends Component

    import React, { Component } from 'react';
    
    class Clock extends Component {
      constructor(props){
        super(props);
        this.state = {currentCount: 10}
      }
      timer() {
        this.setState({
          currentCount: this.state.currentCount - 1
        })
        if(this.state.currentCount < 1) { 
          clearInterval(this.intervalId);
        }
      }
      componentDidMount() {
        this.intervalId = setInterval(this.timer.bind(this), 1000);
      }
      componentWillUnmount(){
        clearInterval(this.intervalId);
      }
      render() {
        return(
          <div>{this.state.currentCount}</div>
        );
      }
    }
    
    module.exports = Clock;
    
    0 讨论(0)
  • 2020-11-30 21:19

    Thanks @dotnetom, @greg-herbowicz

    If it returns "this.state is undefined" - bind timer function:

    constructor(props){
        super(props);
        this.state = {currentCount: 10}
        this.timer = this.timer.bind(this)
    }
    
    0 讨论(0)
  • 2020-11-30 21:19

    Manage setInterval with React Hooks:

      const [seconds, setSeconds] = useState(0)
    
      const interval = useRef(null)
    
      useEffect(() => { if (seconds === 60) stopCounter() }, [seconds])
    
      const startCounter = () => interval.current = setInterval(() => {
        setSeconds(prevState => prevState + 1)
      }, 1000)
    
      const stopCounter = () => clearInterval(interval.current)
    
    0 讨论(0)
  • 2020-11-30 21:20

    Updating state every second in the react class. Note the my index.js passes a function that return current time.

    import React from "react";
    
    class App extends React.Component {
      constructor(props){
        super(props)
    
        this.state = {
          time: this.props.time,
    
        }        
      }
      updateMe() {
        setInterval(()=>{this.setState({time:this.state.time})},1000)        
      }
      render(){
      return (
        <div className="container">
          <h1>{this.state.time()}</h1>
          <button onClick={() => this.updateMe()}>Get Time</button>
        </div>
      );
    }
    }
    export default App;
    
    0 讨论(0)
  • 2020-11-30 21:22

    I see 4 issues with your code:

    • In your timer method you are always setting your current count to 10
    • You try to update the state in render method
    • You do not use setState method to actually change the state
    • You are not storing your intervalId in the state

    Let's try to fix that:

    componentDidMount: function() {
       var intervalId = setInterval(this.timer, 1000);
       // store intervalId in the state so it can be accessed later:
       this.setState({intervalId: intervalId});
    },
    
    componentWillUnmount: function() {
       // use intervalId from the state to clear the interval
       clearInterval(this.state.intervalId);
    },
    
    timer: function() {
       // setState method is used to update the state
       this.setState({ currentCount: this.state.currentCount -1 });
    },
    
    render: function() {
        // You do not need to decrease the value here
        return (
          <section>
           {this.state.currentCount}
          </section>
        );
    }
    

    This would result in a timer that decreases from 10 to -N. If you want timer that decreases to 0, you can use slightly modified version:

    timer: function() {
       var newCount = this.state.currentCount - 1;
       if(newCount >= 0) { 
           this.setState({ currentCount: newCount });
       } else {
           clearInterval(this.state.intervalId);
       }
    },
    
    0 讨论(0)
提交回复
热议问题