useWatchPausable()
Last updated: 24/04/2026
Overview
useWatchPausable behaves like a standard value watcher-callback(value, previous) on each effect when active-but pause() / resume() toggle isActive. When paused, value can change without invoking the callback and previousRef is not updated during those commits (so when you resume, the next run can still use the “last seen” previous from before pause, depending on React’s batching). The hook returns { isActive, pause, resume }. Same deps spread pattern as other watch helpers. Use to temporarily silence expensive side effects (analytics, network).
What it accepts
value:Tcallback:(value: T, previous: T | undefined) => void- Optional
deps:DependencyList
What it returns
isActive:boolean-falsewhen pausedpause:() => voidresume:() => void
Usage
A counter drives n; when paused, ticks do not update last.
import { useState } from 'react'
import useWatchPausable from '@dedalik/use-react/useWatchPausable'
function Example() {
const [n, setN] = useState(0)
const [last, setLast] = useState<number | null>(null)
const { isActive, pause, resume } = useWatchPausable(n, (v) => {
setLast(v)
})
return (
<div>
<p>
n: <strong>{n}</strong> - last seen by watcher: <strong>{last ?? '-'}</strong>
</p>
<p>watcher: {isActive ? 'active' : 'paused'}</p>
<button type='button' onClick={() => setN((x) => x + 1)}>
+1
</button>{' '}
<button type='button' onClick={isActive ? pause : resume}>
{isActive ? 'Pause' : 'Resume'}
</button>
</div>
)
}
export default function Demo() {
return <Example />
}API Reference
useWatchPausable
Signature: useWatchPausable<T>(value: T, callback: (value: T, previous: T | undefined) => void, deps?: DependencyList): WatchPausableControls
Parameters
valuecallbackdeps
Returns
WatchPausableControls
Copy-paste hook
TypeScript
import { DependencyList, useCallback, useEffect, useRef, useState } from 'react'
export interface WatchPausableControls {
isActive: boolean
pause: () => void
resume: () => void
}
/**
* Watcher that can be paused/resumed.
*/
export default function useWatchPausable<T>(
value: T,
callback: (value: T, previous: T | undefined) => void,
deps: DependencyList = [],
): WatchPausableControls {
const previousRef = useRef<T | undefined>(undefined)
const [isActive, setIsActive] = useState(true)
const pause = useCallback(() => setIsActive(false), [])
const resume = useCallback(() => setIsActive(true), [])
useEffect(() => {
if (!isActive) return
callback(value, previousRef.current)
previousRef.current = value
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isActive, value, ...deps])
return { isActive, pause, resume }
}JavaScript
import { useCallback, useEffect, useRef, useState } from 'react'
/**
* Watcher that can be paused/resumed.
*/
export default function useWatchPausable(value, callback, deps = []) {
const previousRef = useRef(undefined)
const [isActive, setIsActive] = useState(true)
const pause = useCallback(() => setIsActive(false), [])
const resume = useCallback(() => setIsActive(true), [])
useEffect(() => {
if (!isActive) return
callback(value, previousRef.current)
previousRef.current = value
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isActive, value, ...deps])
return { isActive, pause, resume }
}