useInterval
useInterval runs a body on a repeat for as long as the component exists and
the body is a function.
useInterval(body: TimerBody, options?: { everyMs: Int }, on?: Ref): TimerReference
Section titled “Reference”useInterval(body, options?, on?)
Section titled “useInterval(body, options?, on?)” const tick = useInterval(paused === 1 ? undefined : () => { if (left === 0) { tick.stop(); } else { setLeft(left - 1); } }, { everyMs: 1000 });Parameters
Section titled “Parameters”body: A function taking no arguments, orundefinedon the arm of a conditional that should clear the timer rather than set one.options.everyMs: A number of milliseconds between runs. Left off, the body runs every client cycle.on: A ref naming the component the timer lives on — its host. Defaults to this component’s root.
Returns
Section titled “Returns”A Timer with one method:
stop(): Stops it. Safe to call from inside the body itself.
Caveats
Section titled “Caveats”- The phase is global, not measured from when the component appeared.
“Every 1000 ms” means on the second, so several components on one period tick
together, and the first tick lands on the next multiple of the period. For
“1000 ms from now”, use
useDelay. - It survives a rebuild of its component.
- A timer that should end has to end itself. Nothing stops it for you.
- One timer per host (
TS2E213). Name a different host with the third argument, or split the component. - A hidden host does not tick. A timer under a
hidedoes not tick, and picks up where it left when shown; a host 0 wide or 0 tall never ticks at all (TS2E252). See Timers. - A tick lands at or after the time asked for, within about 20 milliseconds.
- A
.map()row cannot call a hook (TS2E203). For a timer on each row, make the row a component:{ROWS.map((r, i) => <Row r={r} y={i * 16} />)}.
useInterval(() => { setSeconds(seconds + 1); }, { everyMs: 1000 }); useInterval(() => { setBlink(1 - blink); }, { everyMs: 500 }); // the timer is takenCounting down
Section titled “Counting down” const [left, setLeft] = useState(60); const [paused, setPaused] = useState(0);
const tick = useInterval(paused === 1 ? undefined : () => { if (left === 0) { tick.stop(); } else { setLeft(left - 1); } }, { everyMs: 1000 });Pausing from outside the body
Section titled “Pausing from outside the body”While paused is 1 the body is undefined, which clears the timer.
<layer x="right" y={2} w={56} h={18} onClick={() => { setPaused(1 - paused); }}>Naming the host
Section titled “Naming the host” useInterval(() => { setTicks(ticks + 1); }, { everyMs: 200 }, host); <layer ref={host} w="fill" h="fill">Troubleshooting
Section titled “Troubleshooting”The first tick is too early
Section titled “The first tick is too early”The phase is global, so the first tick lands at the next multiple of the period
rather than a full period after the component appeared. Use
useDelay if that matters.
The timer keeps running after I expected it to stop
Section titled “The timer keeps running after I expected it to stop”Call tick.stop(), or make the body undefined on an arm. Reaching a
condition does not stop a timer.
The timer stopped when I hid the panel
Section titled “The timer stopped when I hid the panel”If it must keep counting while hidden, host it on a
component that is not under the hide.
That component already has a timer
Section titled “That component already has a timer”Two intervals on one host. Give the second a host of its own with the third argument, or move it into a component of its own.