英文:
setState does not update inside intervalRef
问题
以下是您要翻译的代码部分:
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'));
请注意,代码中使用了React库的相关部分,这些部分不会被翻译。如果您有任何其他问题或需要进一步帮助,请随时告诉我。
英文:
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.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
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'));
<!-- language: lang-html -->
<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>
<!-- end snippet -->
The interval works completely fine since the console.log(count)
prints ok, but why doesn't setCount work?
答案1
得分: 0
由于useEffect
不依赖于count
,所以闭包内的count
始终为0,0 + 1 -> 1。在调用setState
时,请使用更新函数。更新函数将使用当前状态进行调用。
注意:你还应该从useEffect
返回一个清理函数,以便在组件卸载时清除定时器。
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); // 清理函数
},
[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"));
英文:
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.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
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"));
<!-- language: lang-html -->
<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>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论