正如其他人所指出的,问题是useState只调用一次 (as deps = []) 来设置间隔:
React.useEffect(() => {
    const timer = window.setInterval(() => {
        setTime(time + 1);
    }, 1000);
    return () => window.clearInterval(timer);
}, []);
然后,每次setInterval滴答时,它实际上会调用setTime(time + 1),但time将始终保持setInterval定义回调(闭包)时的初始值。
您可以使用useState's setter的替代形式并提供回调而不是您要设置的实际值(就像 with setState):
setTime(prevTime => prevTime + 1);
但我鼓励您创建自己的useInterval钩子,以便您可以通过setInterval 声明式使用来 DRY 和简化代码,正如 Dan Abramov 在使用 React Hooks 制作 setInterval 声明式中所建议的那样:
function useInterval(callback, delay) {
  const intervalRef = React.useRef();
  const callbackRef = React.useRef(callback);
  // Remember the latest callback:
  //
  // Without this, if you change the callback, when setInterval ticks again, it
  // will still call your old callback.
  //
  // If you add `callback` to useEffect's deps, it will work fine but the
  // interval will be reset.
  React.useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);
  // Set up the interval:
  React.useEffect(() => {
    if (typeof delay === 'number') {
      intervalRef.current = window.setInterval(() => callbackRef.current(), delay);
      // Clear interval if the components is unmounted or the delay changes:
      return () => window.clearInterval(intervalRef.current);
    }
  }, [delay]);
  
  // Returns a ref to the interval ID in case you want to clear it manually:
  return intervalRef;
}
const Clock = () => {
  const [time, setTime] = React.useState(0);
  const [isPaused, setPaused] = React.useState(false);
        
  const intervalRef = useInterval(() => {
    if (time < 10) {
      setTime(time + 1);
    } else {
      window.clearInterval(intervalRef.current);
    }
  }, isPaused ? null : 1000);
  return (<React.Fragment>
    <button onClick={ () => setPaused(prevIsPaused => !prevIsPaused) } disabled={ time === 10 }>
        { isPaused ? 'RESUME ⏳' : 'PAUSE 🚧' }
    </button>
    <p>{ time.toString().padStart(2, '0') }/10 sec.</p>
    <p>setInterval { time === 10 ? 'stopped.' : 'running...' }</p>
  </React.Fragment>);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
body,
button {
  font-family: monospace;
}
body, p {
  margin: 0;
}
p + p {
  margin-top: 8px;
}
#app {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100vh;
}
button {
  margin: 32px 0;
  padding: 8px;
  border: 2px solid black;
  background: transparent;
  cursor: pointer;
  border-radius: 2px;
}
<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>
 
 
除了生成更简单和更清晰的代码之外,这还允许您通过简单地传递自动暂停(和清除)间隔delay = null并返回间隔 ID,以防您想手动取消它(这在 Dan 的帖子中没有涉及)。
实际上,这也可以改进,以便它在未delay暂停时不会重新启动,但我想对于大多数用例来说这已经足够了。
如果您正在为setTimeout而不是寻找类似的答案setInterval,请查看:https : //stackoverflow.com/a/59274757/3723993。
您还可以找到的声明版本setTimeout和setInterval,useTimeout并useInterval以书面的typescript一些额外的钩https://www.npmjs.com/package/@swyg/corre。