setState 不会在 intervalRef 内更新 [英] setState does not update inside intervalRef
问题描述
我正在尝试学习如何使用 intervalRef,其中我将状态增加 100 毫秒,但由于某种原因它不起作用.
const {useState,useEffect,useRef} = React;功能定时器({active}){const intervalRef = useRef(null)const [count, setCount] = useState(0)useEffect(()=>{如果(活动){intervalRef.current = setInterval(()=>{控制台日志(计数);设置计数(计数 + 1);},100)} 别的 {clearInterval(intervalRef.current)}},[积极的])返回 (<p>{count}</p>)}函数主(){const [active, setActive] = useState(false)返回 (<div><Timer active={active}/><button onClick={()=>{setActive(!active)}}>切换</button>
)}ReactDOM.render(, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script><div id="app"></div>
间隔工作完全正常,因为 console.log(count)
打印正常,但为什么 setCount 不起作用?
由于useEffect
不依赖于count
,count
里面的闭包始终为 0,并且 0 + 1 -> 1.使用 updater 函数 当您调用 setState
时.使用当前状态调用更新函数.
注意:你还应该从 useEffect
返回一个清理函数,如果组件被卸载,它将清除间隔.
const { useState, useEffect, useRef } = React;功能定时器({ 活动}){const intervalRef = useRef(null);const [count, setCount] = useState(0);使用效果(() =>{如果(活动){intervalRef.current = setInterval(() => {setCount(count => count + 1);}, 100);} 别的 {clearInterval(intervalRef.current);}返回 () =>clearInterval(intervalRef.current);//清理函数},[积极的]);返回<p>{count}</p>;}函数主(){const [active, setActive] = useState(false);返回 (<div><Timer active={active}/><button onClick={() =>{ setActive(!active);}}>切换</button>
);}ReactDOM.render(, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script><div id="app"></div>
I'm trying to learn how to use intervalRef where I increment the state ever 100 ms, but for some reason it does not work.
const {useState,useEffect,useRef} = React;
function Timer({active}) {
const intervalRef = useRef(null)
const [count, setCount] = useState(0)
useEffect(()=>{
if(active){
intervalRef.current = setInterval(()=>{
console.log(count);
setCount(count + 1);
},100)
} else {
clearInterval(intervalRef.current)
}
},[active])
return (
<p>{count}</p>
)
}
function Main() {
const [active, setActive] = useState(false)
return (
<div>
<Timer active={active}/>
<button onClick={()=>{setActive(!active)}}>Toggle</button>
</div>
)
}
ReactDOM.render(<Main />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="app"></div>
The interval works completely fine since the console.log(count)
prints ok, but why doesn't setCount work?
Since the useEffect
is not dependant on count
, the count
inside the closure is always 0, and 0 + 1 -> 1. Use an updater function when you call setState
. The update function is called with the current state.
Note: you should also return a cleanup function from useEffect
, that will clear the interval if the component is unmounted.
const { useState, useEffect, useRef } = React;
function Timer({ active }) {
const intervalRef = useRef(null);
const [count, setCount] = useState(0);
useEffect(
() => {
if (active) {
intervalRef.current = setInterval(() => {
setCount(count => count + 1);
}, 100);
} else {
clearInterval(intervalRef.current);
}
return () => clearInterval(intervalRef.current); // cleanup function
},
[active]
);
return <p>{count}</p>;
}
function Main() {
const [active, setActive] = useState(false);
return (
<div>
<Timer active={active} />
<button onClick={() => { setActive(!active); }}>Toggle</button>
</div>
);
}
ReactDOM.render(<Main />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="app"></div>
这篇关于setState 不会在 intervalRef 内更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!