OptionalArray
(type).nextState = nextStateFromAction(action, state)
: get next state fromsetState
action.[state, toggle] = useToggle(init = false)
:toggle()
to toggle booleanstate
state, or,toggle(true/false)
to set state.[state, enable] = useTurnOn()
:enable()
to set state totrue
.[state, disable] = useTurnOff()
:disable()
to set state tofalse
.unmountedRef = useUnmountedRef()
: get a ref whose value istrue
when component is unmounted. Note, from react 18, the effect is sometimes unmounted and mounted again.mountedRef = useMountedRef()
: get a ref whose value istrue
when component is mounted. Note: ref's value is not set tofalse
when component is unmounted.mounted = useMounted()
: get a boolean whose value istrue
when component is mounted. Note: the value is not set tofalse
when component is unmounted.timedout = useTimedOut(timeout)
: get a boolean whose value istrue
aftertimeout
ms.state = useDebounce(value, timeout)
: get a debounced value.state
is updated after at leasttimeout
ms.memoValue = useDeepMemo(value)
: get a memoized value.value
is compared bydeep-equal
package.update = useForceUpdate()
: get a function to force re-render component.prefRef = usePrevRef(value)
: get a ref whose value is the previousvalue
.[state, setState] = useDefaultState(defaultState)
: whendefaultState
changes, setstate
todefaultState
. Note: we currently rely on deps array to trigger the effect. Need to check if react never fires the effect when the deps array is the same.useEffectWithPrevDeps((prevDeps) => {}, [...deps])
: similar touseEffect
, but also provides previous deps to the effect function.useEffectOnce(() => {}, [...deps])
: similar touseEffect
, but fires only once.useLayoutEffectWithPrevDeps((prevDeps) => {}, [...deps])
:useLayoutEffect
version ofuseEffectWithPrevDeps
.[state, setState, stateRef] = useEnhancedState(initialState)
: similar touseState
, but also returns a ref whose value is always the lateststate
.[state, setState, stateRef] = useRefState(initialState)
: similar touseState
.stateRef
's value is set immediately and synchronously aftersetState
is called. Note:initialState
can not be a function.[loading, makeAtomic] = useAtomicMaker()
: get a function to make a function atomic by callingawait makeAtomic(cb)(...params)
.loading
istrue
when the atomic function is running. If another atomic function is called when the previous one is running, the new one returnsundefined
.[loading, atomicCb] = useAtomicCallback(cb)
: similar touseAtomicMaker
withatomicCb = makeAtomic(cb)
.ref = useRefValue(value)
: similar touseEffectEvent
, get a ref whose value is always the latestvalue
.[state, setState] = useAnimationState(elmRef, initialValue)
: delay state change if animation/transition (on element whose ref iselmRef
) is running (i.e., only update state after the animation ends). Note:ref.current
should be defined as soon as possible (for e.g., from the first effect call). Otherwise, it will not possible to listen to animation/transition events. Note: if the animation fires before the effect is called which usually happens (and even before any javascript runs),animationstart
/transitionstart
is not caught which causes the state to be updated immediately ifsetState()
is called.useConfirmDiscard(msg)
: show confirm dialog when user tries to reload the page.msg
is the message to show. Ifmsg
is falsy, the confirm dialog is disabled.useIsoLayoutEffect
: it is ridiculous that react does not allow to calluseLayoutEffect
in SSR (tested with react <= v17). This hook switches touseLayoutEffect
in browser anduseEffect
in SSR.[width, height] = useWindowSize()
: get window size, listen toresize
event ofwindow
. In SSR,width
andheight
areundefined
. Note: be careful when handling hydration mismatch.{value, setValue} = usePropState(initialState)
: similar touseState
, but the returned value is an object, not an array.scopeId = useScopeId(prefix?: string)
: get a function to generate scoped id.prefix
is the prefix of the id. The id is generated byscopeId(name?: string) = prefix + id + name
.id
is a SSR-statically random number generated byuseId()
.update = useUpdate(getValue)
: get a function to force re-render component.getValue
is a function to get the latest value to compare with the previous value. The latest passedgetValue
is always used (useReducer
specs).lastDefinedValue = useKeep(value)
: keep the last defined value. Ifvalue
isundefined
, the last defined value is returned.useListData()
: utility to load list data. Usage:
const {list, hasPrev, hasNext, loadPrev, loadNext} = useListData({
initial: {
list, // default list
hasNext, // default hasNext
hasPrev, // default hasPrev
},
async load({before, after}) { // function to load data
return {
records, // new records
hasMore, // whether there are more records
}
}
})
When calling loadNext, loadPrev
, if there is an existing running, the new call will not be executed and does nothing.