我正在尝试新的React Hooks,并有一个带有计数器的Clock组件,该计数器应该每秒增加一次。但是,该值不会增加到超过一。
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/[email protected]/umd/react.development.js"></script> <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script> <div id="app"></div>
原因是传递给setInterval的闭包中的回调仅访问time第一个渲染器中的变量,而无法访问time后续渲染器中的新值,因为useEffect()第二次未调用。
setInterval
time
useEffect()
time``setInterval回调中的值始终为0 。
time``setInterval
就像setState您熟悉的状态挂钩一样,状态挂钩有两种形式:一种是处于更新状态的状态,另一种是将当前状态传入的回调形式。您应该使用第二种形式,并读取setState回调中的最新状态值以在递增之前,请确保您具有最新的状态值。
setState
奖励:替代方法 Dan Abramov setInterval在他的博客文章中深入探讨了有关使用钩子的主题,并提供了解决此问题的替代方法。强烈建议阅读!
奖励:替代方法
Dan Abramov setInterval在他的博客文章中深入探讨了有关使用钩子的主题,并提供了解决此问题的替代方法。强烈建议阅读!
function Clock() { const [time, setTime] = React.useState(0); React.useEffect(() => { const timer = window.setInterval(() => { setTime(prevTime => prevTime + 1); // <-- Change this line! }, 1000); return () => { window.clearInterval(timer); }; }, []); return ( <div>Seconds: {time}</div> ); } ReactDOM.render(<Clock />, document.querySelector('#app')); <script src="https://unpkg.com/[email protected]/umd/react.development.js"></script> <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script> <div id="app"></div>