A collection of useful hooks for data structures and logic, designed for efficiency and performance
An Object or array. Rerenders on mutation. Will recursively listen on object/array children (not class instances). This functions using proxy references, allowing React to detect reference changes without having to copy the data over and over again.
Tip
Force state updates with forceUpdate(), the third item of the tuple
function Component () {
const [object, setObject] = useObject({ foo: { bar: 'baz' } })
useEffect(() => {
console.log('Object updated!', object)
}, [object])
useEffect(() => {
console.log('Foo updated!', object.foo)
}, [object.foo])
return (
<button onClick={() => { object.foo.bar = 'foobar' }}>CLICK ME</button>
)
}Debounce state changes with a delay
function Component () {
const [debounced, setState, real] = useDebouncedState('', 300)
useEffect(() => {
console.log(`Debounced value: ${debounced}`)
}, [debounced])
return (
<input value={real} onChange={(e) => setState(e.currentTarget.value)} />
)
}Handle a promise within render behavior
function Component () {
const {
// 'waiting' | 'resolved' | 'rejected'
state,
result,
error
} = usePromise(() => signedIn && ((abortSignal) -> getUserProfile(abortSignal)))
}A Set. Rerenders upon mutation. To listen on changes in hook dependencies, coerce to a numeric type (+set)
Tip
Force state updates with set.forceUpdate()
function Component () {
const set = useSet<string>()
useEffect(() => {
console.log('set items:')
for (const item of set) console.log(item)
}, [set, +set])
return (
<button onClick={() => set.add('foo')}>CLICK ME</button>
)
}A Map. Rerenders upon mutation. To listen on changes in hook dependencies, coerce to a numeric type (+map)
Tip
Force state updates with map.forceUpdate()
function Component () {
const map = useMap<string, number>()
useEffect(() => {
console.log('map items:')
for (const [key, value] of map.entries()) console.log(`[${key}]: ${value}`)
}, [map, +map])
return (
<button onClick={() => map.set('foo', 52)}>CLICK ME</button>
)
}Memoize changing array references if the contents remain the same
function Component ({ array }: { array: string[] }) {
const memoed = useArrayMemo(array)
// Only runs if the contents of the array are different
useEffect(() => {
console.log('Array updated!', memoed)
}, [memoed])
return (
<button onClick={() => { object.foo.bar = 'foobar' }}>CLICK ME</button>
)
}Prevent user navigation/window closing when there are unsaved changes (NextJS router compatible)
function Component () {
const [isUnsaved, setIsUnsaved] = useState(false)
useUnsaved(isUnsaved)
}