useWhenever()
Last updated: 24/04/2026
Overview
useWhenever fires callback() only on the transition from falsy → truthy for condition: on each run it compares condition to the value stored in previousRef. It does not run when condition stays true across renders, and it does not run on true → false. An optional extra deps list is spread into the effect (after condition), so unrelated keys can re-run the check. For “run while true every time” use a different pattern (e.g. useWatchImmediate on a boolean or useEffect on [condition]).
What it accepts
condition:booleancallback:() => void- Optional
deps:DependencyList
What it returns
void
Usage
When on first becomes true, append a one-line message; toggling off/on fires again on the next false → true.
import { useState } from 'react'
import useWhenever from '@dedalik/use-react/useWhenever'
function Example() {
const [on, setOn] = useState(false)
const [log, setLog] = useState<string[]>([])
useWhenever(on, () => {
setLog((d) => [...d, 'Condition became true at ' + new Date().toLocaleTimeString()])
})
return (
<div>
<p>
<label>
<input type='checkbox' checked={on} onChange={(e) => setOn(e.target.checked)} /> Online
</label>
</p>
<ol>
{log.map((l, i) => (
<li key={i}>{l}</li>
))}
</ol>
</div>
)
}
export default function Demo() {
return <Example />
}API Reference
useWhenever
Signature: useWhenever(condition: boolean, callback: () => void, deps?: DependencyList): void
(Package import: import useWhenever from '@dedalik/use-react/useWhenever'.)
Parameters
conditioncallbackdeps
Returns
void
Copy-paste hook
TypeScript
import { DependencyList, useEffect, useRef } from 'react'
/**
* Runs callback when condition turns true.
*/
export default function useWhenever(condition: boolean, callback: () => void, deps: DependencyList = []): void {
const previousRef = useRef(condition)
useEffect(() => {
if (condition && !previousRef.current) callback()
previousRef.current = condition
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [condition, ...deps])
}JavaScript
import { useEffect, useRef } from 'react'
/**
* Runs callback when condition turns true.
*/
export default function useWhenever(condition, callback, deps = []) {
const previousRef = useRef(condition)
useEffect(() => {
if (condition && !previousRef.current) callback()
previousRef.current = condition
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [condition, ...deps])
}