useOnChange.ts27 lines · main
| 1 | import { useState } from 'react' |
| 2 | |
| 3 | function 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 | */ |
| 16 | export 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 | } |