useWatchArray()
Last updated: 24/04/2026
Overview
useWatchArray runs callback(next, previous, added, removed) on every effect where value (or deps) changes. added and removed are computed with includes ( reference/shallow equality per item): items present in next but not previous, and in previous but not next. It does not do deep diffing of element fields-use stable ids (strings) or immutable item references for predictable results. After each run, prevRef is set to the value array reference. Duplicate values in a list can make includes-based diffs ambiguous; treat as a set-like list of unique items for clear added/removed semantics.
What it accepts
value:T[]callback:(value: T[], previous: T[], added: T[], removed: T[]) => void- Optional
deps:DependencyList
What it returns
void
Usage
Tag list of strings: add and remove; show last added / removed side by side.
import { useState } from 'react'
import useWatchArray from '@dedalik/use-react/useWatchArray'
function Example() {
const [tags, setTags] = useState<string[]>(['a', 'b'])
const [summary, setSummary] = useState('')
useWatchArray(tags, (next, _prev, added, removed) => {
setSummary(`added: [${added.join(', ')}] · removed: [${removed.join(', ')}] · size ${next.length}`)
})
return (
<div>
<p>tags: {tags.join(', ')}</p>
<p>
<button type='button' onClick={() => setTags((t) => [...t, 'c'])}>
add c
</button>{' '}
<button type='button' onClick={() => setTags((t) => t.filter((x) => x !== 'a'))}>
remove a
</button>
</p>
<p>
<small>{summary || '-'}</small>
</p>
</div>
)
}
export default function Demo() {
return <Example />
}API Reference
useWatchArray
Signature: useWatchArray<T>(value: T[], callback: (value: T[], previous: T[], added: T[], removed: T[]) => void, deps?: DependencyList): void
Parameters
valuecallbackdeps
Returns
void
Copy-paste hook
TypeScript
import { DependencyList, useEffect, useRef } from 'react'
/**
* Watches array changes and reports added/removed items.
*/
export default function useWatchArray<T>(
value: T[],
callback: (value: T[], previous: T[], added: T[], removed: T[]) => void,
deps: DependencyList = [],
): void {
const prevRef = useRef<T[]>(value)
useEffect(() => {
const previous = prevRef.current
const added = value.filter((item) => !previous.includes(item))
const removed = previous.filter((item) => !value.includes(item))
callback(value, previous, added, removed)
prevRef.current = value
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value, ...deps])
}JavaScript
import { useEffect, useRef } from 'react'
/**
* Watches array changes and reports added/removed items.
*/
export default function useWatchArray(value, callback, deps = []) {
const prevRef = useRef(value)
useEffect(() => {
const previous = prevRef.current
const added = value.filter((item) => !previous.includes(item))
const removed = previous.filter((item) => !value.includes(item))
callback(value, previous, added, removed)
prevRef.current = value
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value, ...deps])
}