我正在尝试新的React钩子,并有一个时钟组件,它的时间值应该每秒钟增加。但是,该值不会超过1。

function Clock() { const [time, setTime] = React.useState(0); React.useEffect(() => { const timer = window.setInterval(() => { setTime(time + 1); }, 1000); return () => { window.clearInterval(timer); }; }, []); return ( <div>Seconds: {time}</div> ); } ReactDOM.render(<Clock />, document.querySelector('#app')); <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>


当前回答

  const [loop, setLoop] = useState(0);
  
  useEffect(() => {
    setInterval(() => setLoop(Math.random()), 5000);
  }, []);

  useEffect(() => {
    // DO SOMETHING...
  }, [loop])

其他回答

const [seconds, setSeconds] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds((seconds) => {
        if (seconds === 5) {
          setSeconds(0);
          return clearInterval(interval);
        }
        return (seconds += 1);
      });
    }, 1000);
  }, []);

注意:这将有助于使用useState钩子更新和重置计数器。5秒后秒停止。因为首先改变setSecond值,然后在setInterval内用更新的秒停止计时器。as useEffect运行一次。

function Clock() {
  const [time, setTime] = React.useState(0);
  React.useEffect(() => {
    const timer = window.setInterval(() => {
      setTime(time => time + 1);// **set callback function here** 
    }, 1000);
    return () => {
      window.clearInterval(timer);
    };
  }, []);

  return (
    <div>Seconds: {time}</div>
  );
}

ReactDOM.render(<Clock />, document.querySelector('#app'));

另一种解决方案是使用useReducer,因为它总是被传递当前状态。

function Clock() { const [time, dispatch] = React.useReducer((state = 0, action) => { if (action.type === 'add') return state + 1 return state }); React.useEffect(() => { const timer = window.setInterval(() => { dispatch({ type: 'add' }); }, 1000); return () => { window.clearInterval(timer); }; }, []); return ( <div>Seconds: {time}</div> ); } ReactDOM.render(<Clock />, document.querySelector('#app')); <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

对于那些寻找极简解决方案的人:

停止间隔N秒后,和 能够重置它多次再次按下按钮。

(我不是React专家,我的同事要求我帮忙,我写了这篇文章,我想其他人可能会觉得它有用。)


  const [disabled, setDisabled] = useState(true)
  const [inter, setInter] = useState(null)
  const [seconds, setSeconds] = useState(0)

  const startCounting = () => {
    setSeconds(0)
    setDisabled(true)
    setInter(window.setInterval(() => {
        setSeconds(seconds => seconds + 1)
    }, 1000))
  }

  useEffect(() => {
      startCounting()
  }, [])

  useEffect(() => {
    if (seconds >= 3) {
        setDisabled(false)
        clearInterval(inter)
    }
  }, [seconds])

  return (<button style = {{fontSize:'64px'}}
      onClick={startCounting}
      disabled = {disabled}>{seconds}</button>)
}

当提供空输入列表时,useEffect函数只在组件挂载时计算一次。

setInterval的另一个替代方法是在每次状态更新时使用setTimeout设置新的间隔时间:

  const [time, setTime] = React.useState(0);
  React.useEffect(() => {
    const timer = setTimeout(() => {
      setTime(time + 1);
    }, 1000);
    return () => {
      clearTimeout(timer);
    };
  }, [time]);

setTimeout对性能的影响很小,一般可以忽略。除非组件对时间敏感,以至于新设置的超时会导致不良影响,否则setInterval和setTimeout方法都是可以接受的。