useOnChange.ts27 lines · main
1import { useState } from 'react'
2
3function isDifferent(a: unknown, b: unknown): boolean {
4 if (Array.isArray(a) && Array.isArray(b)) {
5 return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]))
6 }
7
8 return a !== b
9}
10
11/**
12 * @param value - state to watch
13 * @param onChange - when the state changed
14 * @param isUpdated - a function that determines if the state is updated
15 */
16export function useOnChange<T>(
17 value: T,
18 onChange: (current: T, previous: T) => void,
19 isUpdated: (prev: T, current: T) => boolean = isDifferent
20): void {
21 const [prev, setPrev] = useState<T>(value)
22
23 if (isUpdated(prev, value)) {
24 onChange(value, prev)
25 setPrev(value)
26 }
27}