SetInterval "Stacking" 相互叠加
SetInterval "Stacking" on top of each other
我正在处理这个使用 setInterval 的项目,但我在理解 setInterval 的工作原理时遇到了一些问题。我遇到的问题是,每次调用 setInterval 时,该函数似乎都堆叠在一起,导致对象快速出现多次。我不确定在这种情况下我做错了什么。谁能帮帮我谢谢。
const [hit, setHit] = useState(0)
const [count, setCount] = useState(0)
var timer = null
var funcCalls = 0
const hitSound = new Audio("/hit.wav")
useEffect(()=>{
timer = setInterval(moveSquare, 2000)
},[])
function handleHit(){
hitSound.play()
setHit(hit+1)
resetSquare()
}
function resetSquare(){
clearInterval(timer)
moveSquare()
timer = setInterval(moveSquare, 2000)
}
function moveSquare(){
const gameContainer = document.getElementById("game-container")
const height = gameContainer.offsetHeight
const width = gameContainer.offsetWidth
const square = document.getElementById("square")
square.style.top = (Math.random() * (height - 100)) + "px";
square.style.left = (Math.random() * (width - 100)) + "px";
}
return (
<>
<section className='game-section'>
<div className='counter'>
{hit}
{count}
</div>
<div className='game-container' id = "game-container">
<div className="square" id = "square" onClick={handleHit}></div>
</div>
</section>
</>
)
这是因为 timer
值未跨渲染保存,因此您无法取消它。
var timer = null // <-- no
const [timer, setTimer] = useState(null) // <-- yes
...
// later in useEffect() and resetSquare()
// save the timer using setTimer(timer)
原因在别处:您的组件(and/or 及其父组件)已重新创建。一般来说,只有几个原因,但很难在不调试的情况下指向特定的代码行:
- 条件渲染(例如在请求期间和在渲染元素后再次显示微调器)
- 或提供不同的
key
道具
- 或者你错误地将组件声明(函数或 class 或包装到 HOC 中)放在其他组件的渲染代码中,每次重新渲染父组件时,组件的声明都会变得引用不同
另一个根本原因:您的 useEffect
没有清理。虽然它应该。即使没有第一个原因,你也不会有多个并发计时器,但你仍然会有在你离开时不会停止的计时器。
useEffect(()=>{
timer = setInterval(moveSquare, 2000)
return () => clearInterval(timer);
},[])
官方文档中有关清理的更多信息:https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup
我正在处理这个使用 setInterval 的项目,但我在理解 setInterval 的工作原理时遇到了一些问题。我遇到的问题是,每次调用 setInterval 时,该函数似乎都堆叠在一起,导致对象快速出现多次。我不确定在这种情况下我做错了什么。谁能帮帮我谢谢。
const [hit, setHit] = useState(0)
const [count, setCount] = useState(0)
var timer = null
var funcCalls = 0
const hitSound = new Audio("/hit.wav")
useEffect(()=>{
timer = setInterval(moveSquare, 2000)
},[])
function handleHit(){
hitSound.play()
setHit(hit+1)
resetSquare()
}
function resetSquare(){
clearInterval(timer)
moveSquare()
timer = setInterval(moveSquare, 2000)
}
function moveSquare(){
const gameContainer = document.getElementById("game-container")
const height = gameContainer.offsetHeight
const width = gameContainer.offsetWidth
const square = document.getElementById("square")
square.style.top = (Math.random() * (height - 100)) + "px";
square.style.left = (Math.random() * (width - 100)) + "px";
}
return (
<>
<section className='game-section'>
<div className='counter'>
{hit}
{count}
</div>
<div className='game-container' id = "game-container">
<div className="square" id = "square" onClick={handleHit}></div>
</div>
</section>
</>
)
这是因为 timer
值未跨渲染保存,因此您无法取消它。
var timer = null // <-- no
const [timer, setTimer] = useState(null) // <-- yes
...
// later in useEffect() and resetSquare()
// save the timer using setTimer(timer)
原因在别处:您的组件(and/or 及其父组件)已重新创建。一般来说,只有几个原因,但很难在不调试的情况下指向特定的代码行:
- 条件渲染(例如在请求期间和在渲染元素后再次显示微调器)
- 或提供不同的
key
道具 - 或者你错误地将组件声明(函数或 class 或包装到 HOC 中)放在其他组件的渲染代码中,每次重新渲染父组件时,组件的声明都会变得引用不同
另一个根本原因:您的 useEffect
没有清理。虽然它应该。即使没有第一个原因,你也不会有多个并发计时器,但你仍然会有在你离开时不会停止的计时器。
useEffect(()=>{
timer = setInterval(moveSquare, 2000)
return () => clearInterval(timer);
},[])
官方文档中有关清理的更多信息:https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup