自定义挂钩 SetInterval
Custom Hooks SetInterval
我正在关注 Dan Abramov 的这篇文章:
https://overreacted.io/making-setinterval-declarative-with-react-hooks/
在文章中,Dan 创建了一个自定义的 useInterval 挂钩,以创建一个动态的 setInterval。
钩子看起来像这样:
export default function useInterval(callback, delay) {
//this useInterval function will be called whenever the parent component renders.
// on render, savedCallback.current gets set to whatever the callback is, if the callback
// has changed
const savedCallback = useRef();
console.log("called")
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
/**
* Likewise, the set interval is set off,
* and if delay is
*/
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => {
console.log("clearEed!")
clearInterval(id);
}
}
}, [delay]);
}
虽然有一部分我不明白,它在这里:
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => {
console.log("clearEed!")
clearInterval(id);
}
}
}, [delay]);
我了解到如果延迟发生变化,则会调用此useEffect。回调分配给 tick,然后如果延迟不为 null,则将 id 设置为 SetInterval,并将 tick 和延迟作为参数。这一切都是有道理的。但是接下来发生的事情对我来说很奇怪。我知道 useEffect 可以在组件卸载时使用 return 语句,但为什么我们要清除之前设置的间隔?如果有人能帮我解决这个问题,我将不胜感激。
特别是,我真的很想帮助理解这些行:
if (delay !== null) {
let id = setInterval(tick, delay);
return () => {
console.log("clearEed!")
clearInterval(id);
}
}
我是这样使用的:
function TimerWithHooks() {
let [count, setCount] = useState(0);
let [delay, setDelay] = useState(1000);
useInterval(() => {
setCount(count + 1);
}, delay)
const handleDelayChange = evt => {
setDelay(Number(evt.target.value))
}
return (
<>
<h1>{count}</h1>
<input value={delay} onChange={handleDelayChange} />
</>
);
}
export default TimerWithHooks;
我猜 Dan 会在组件卸载时清除计时器,但我认为 beater 在函数执行后才进行此操作。有东西舔这个:
useEffect(() => {
if (delay !== null) {
let timerId = setInterval(
() => {
savedCallback.current();
clearInterval(timerId);
},
delay
);
}
}, [delay]);
When exactly does React clean up an effect?
React performs the cleanup when the component unmounts. However, as we
learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time. We’ll discuss why this helps avoid bugs
and how to opt out of this behavior in case it creates performance
issues later below.
这意味着每次 delay
改变时,Effect 将清除之前的效果,因此每次我们改变延迟时它都会清除计时器,而 NOT 当组件卸载。这样,我们就可以动态调整定时器,而不必担心清除定时器。
我正在关注 Dan Abramov 的这篇文章:
https://overreacted.io/making-setinterval-declarative-with-react-hooks/
在文章中,Dan 创建了一个自定义的 useInterval 挂钩,以创建一个动态的 setInterval。
钩子看起来像这样:
export default function useInterval(callback, delay) {
//this useInterval function will be called whenever the parent component renders.
// on render, savedCallback.current gets set to whatever the callback is, if the callback
// has changed
const savedCallback = useRef();
console.log("called")
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
/**
* Likewise, the set interval is set off,
* and if delay is
*/
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => {
console.log("clearEed!")
clearInterval(id);
}
}
}, [delay]);
}
虽然有一部分我不明白,它在这里:
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => {
console.log("clearEed!")
clearInterval(id);
}
}
}, [delay]);
我了解到如果延迟发生变化,则会调用此useEffect。回调分配给 tick,然后如果延迟不为 null,则将 id 设置为 SetInterval,并将 tick 和延迟作为参数。这一切都是有道理的。但是接下来发生的事情对我来说很奇怪。我知道 useEffect 可以在组件卸载时使用 return 语句,但为什么我们要清除之前设置的间隔?如果有人能帮我解决这个问题,我将不胜感激。
特别是,我真的很想帮助理解这些行:
if (delay !== null) {
let id = setInterval(tick, delay);
return () => {
console.log("clearEed!")
clearInterval(id);
}
}
我是这样使用的:
function TimerWithHooks() {
let [count, setCount] = useState(0);
let [delay, setDelay] = useState(1000);
useInterval(() => {
setCount(count + 1);
}, delay)
const handleDelayChange = evt => {
setDelay(Number(evt.target.value))
}
return (
<>
<h1>{count}</h1>
<input value={delay} onChange={handleDelayChange} />
</>
);
}
export default TimerWithHooks;
我猜 Dan 会在组件卸载时清除计时器,但我认为 beater 在函数执行后才进行此操作。有东西舔这个:
useEffect(() => {
if (delay !== null) {
let timerId = setInterval(
() => {
savedCallback.current();
clearInterval(timerId);
},
delay
);
}
}, [delay]);
When exactly does React clean up an effect? React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time. We’ll discuss why this helps avoid bugs and how to opt out of this behavior in case it creates performance issues later below.
这意味着每次 delay
改变时,Effect 将清除之前的效果,因此每次我们改变延迟时它都会清除计时器,而 NOT 当组件卸载。这样,我们就可以动态调整定时器,而不必担心清除定时器。