iuseful-react-hooks
Version:
'Use'-ful React hooks
725 lines (694 loc) • 25 kB
text/typescript
import { EffectCallback, DependencyList } from 'react';
interface UseBooleanReturn {
/**
* The current boolean value.
*/
value: boolean;
/**
* Function to toggle the boolean value.
*/
toggle: () => void;
/**
* Function to set the boolean value.
* @param param - A boolean value or a function that receives the previous boolean value and returns a new boolean value.
* If a function is provided, it will be called with the previous value to compute the new value.
* @returns new boolean value.
*/
set: (param: boolean | ((prev: boolean) => boolean)) => void;
}
/**
* A custom hook that manages a boolean state with convenient toggle and set functions.
*
* This hook provides a simple way to manage boolean states with built-in functions
* to toggle the value or set it to a specific boolean or computed value.
*
* @param initialValue - The initial boolean value for the state. Defaults to false.
* @returns An object containing the current boolean value, a function to toggle the value, and a function to set the value.
*
* @example
* ```tsx
* function MyComponent() {
* const { value, toggle, set } = useBoolean(false)
*
* return (
* <div>
* <p>Value: {value.toString()}</p>
* <button onClick={toggle}>Toggle</button>
* <button onClick={() => set(true)}>Set True</button>
* <button onClick={() => set(prev => !prev)}>Toggle via function</button>
* </div>
* )
* }
* ```
*/
declare function useBoolean(initialValue?: boolean): UseBooleanReturn;
interface UseBroadcastChannelSenderParams {
/**
* The name of the BroadcastChannel to send messages through.
*/
channelName: string;
}
interface UseBroadcastChannelSenderReturn<T> {
/**
* Function to send a message through the BroadcastChannel.
* Only send clonable data types (e.g., objects, arrays, strings, numbers).
* @param message - The message to send.
*/
send: (message: T) => void;
}
/**
* A custom hook that provides a function to send messages through a BroadcastChannel.
* @returns An object containing the send function and the BroadcastChannel instance.
*/
declare function useBroadcastChannelSender<T>({ channelName, }: UseBroadcastChannelSenderParams): UseBroadcastChannelSenderReturn<T>;
interface UseBroadcastChannelListenerParams<T> {
/**
* The name of the BroadcastChannel to listen to.
*/
channelName: string;
/**
* The function to handle incoming messages.
* @param ev - The message event to handle.
*/
onMessage: (ev: MessageEvent<T>) => void;
/**
* The function to handle errors when receiving messages.
* @param ev - The error event to handle.
*/
onError?: ((ev: Event) => void) | null;
}
/**
* A custom hook that listens for messages on a BroadcastChannel.
*/
declare function useBroadcastChannelListener<T>({ channelName, onMessage, onError, }: UseBroadcastChannelListenerParams<T>): void;
/**
* A custom hook that returns true if the component is rendering for the first time, and false otherwise.
* @returns True if it's the first render, false otherwise.
*/
declare function useIsFirstRender(): boolean;
/**
* Same as `useEffect`, but the effect will only run after the component has mounted.
* This hook is useful for performing side effects that should only happen after the initial render.
* @param effect - The effect callback to run after the component has mounted
* @param deps - The dependency array for the effect
*/
declare function useEffectAfterMount(effect: EffectCallback, deps?: DependencyList): void;
interface UseNearScreenParams<T> {
/**
* A external ref to the element to observe.
* If not provided, a new ref will be created.
* @default null
*/
externalRef?: React.RefObject<T>;
/**
* If true, the observer will be disconnected after the first intersection.
* @default true
*/
once?: boolean;
/**
* The root margin to use for the intersection observer.
* @default '100px'
*/
rootMargin?: string;
}
interface UseNearScreenReturn<TElement> {
/**
* Whether the element is near the viewport.
*/
isNearScreen: boolean;
/**
* A ref to the observed element.
* If {@link UseNearScreenParams.externalRef} is not provided, a new ref will be created.
*/
fromRef: React.RefObject<TElement | null>;
}
/**
* Custom hook to detect if an element is near the viewport.
* @returns An object containing the isNearScreen state and a ref to the observed element.
*/
declare function useNearScreen<TElement extends HTMLElement | null>({ externalRef, once, rootMargin, }?: UseNearScreenParams<TElement>): UseNearScreenReturn<TElement>;
interface UseTimeoutReturn {
/**
* Indicates if the timeout was cleared.
*/
isCleared: boolean;
/**
* Clears the timeout.
*/
clear: () => void;
/**
* Resets the timeout.
*/
reset: () => void;
}
/**
* A custom hook that sets a timeout and provides controls to manage it.
*
* This hook allows you to schedule a callback function to run after a specified delay,
* with the ability to clear or reset the timeout at any time. The callback can be
* synchronous or return a Promise.
*
* @param onTimeout - The callback function to be called when the timeout is reached. Can return a Promise.
* @param delayInMs - The delay in milliseconds before the timeout is triggered.
* @returns An object with timeout control functions and state.
*
* @example
* ```tsx
* function MyComponent() {
* const { isCleared, clear, reset } = useTimeout(() => {
* console.log('Timeout reached!')
* }, 3000)
*
* return (
* <div>
* <p>Timeout cleared: {isCleared.toString()}</p>
* <button onClick={clear}>Clear Timeout</button>
* <button onClick={reset}>Reset Timeout</button>
* </div>
* )
* }
* ```
*/
declare function useTimeout(onTimeout: () => void | Promise<void>, delayInMs: number): UseTimeoutReturn;
interface UseDebouncedValueOptionsParam {
/**
* The debounce delay in milliseconds.
* @default 300
*/
delayInMs?: number;
}
/**
* A hook that returns a debounced version of the input value.
* @param value - The value to debounce.
* @param options - The options for the debounce behavior.
* @returns The debounced value.
*/
declare function useDebouncedValue<T>(value: T, { delayInMs }?: UseDebouncedValueOptionsParam): T;
interface UseDebouncedEffectOptionsParam {
/**
* If true, the effect will run on the first render.
*/
immediate?: boolean;
}
/**
* A custom hook that debounces the execution of a callback function.
*
* This hook allows you to delay the execution of a callback until after a specified
* delay has passed since the last time the dependencies changed. Useful for expensive
* operations that shouldn't run on every render.
*
* @param callback - The callback function to debounce. Can return a Promise.
* @param delayInMs - The delay in milliseconds to wait before calling the callback. Defaults to 150ms.
* @param deps - The dependency array for the effect, similar to useEffect dependencies.
* @param options - Configuration options for the debounced effect.
* @param options.immediate - If true, the effect will run immediately on the first render. Defaults to true.
*
* @example
* ```tsx
* function SearchComponent() {
* const [query, setQuery] = useState('')
* const [results, setResults] = useState([])
*
* useDebouncedEffect(
* async () => {
* if (query) {
* const data = await searchAPI(query)
* setResults(data)
* }
* },
* 300,
* [query],
* { immediate: false }
* )
*
* return (
* <div>
* <input value={query} onChange={(e) => setQuery(e.target.value)} />
* <ul>{results.map(result => <li key={result.id}>{result.name}</li>)}</ul>
* </div>
* )
* }
* ```
*/
declare function useDebouncedEffect(callback: () => void | Promise<void>, delayInMs?: number, deps?: DependencyList, { immediate }?: UseDebouncedEffectOptionsParam): void;
interface UseArrayReturn<T> {
/**
* The current array value.
*/
array: T[];
/**
* Update the array value.
* @param newArray The new array value.
* @returns void
*/
set: (newArray: T[]) => void;
/**
* Add a new item to the end of the array.
* @param item The item to add.
* @returns void
*/
push: (item: T) => void;
/**
* Remove the last item from the array.
* @returns void
*/
pop: () => void;
/**
* Remove an item of the provided index
* @param index The index of the item to remove.
* @returns void
*/
remove: (index: number) => void;
/**
* Clear the array.
*/
clear: () => void;
/**
* Update the array in the provided index
* @param index The index of the item to update.
* @param value The new value to set.
* @returns void
*/
update: (index: number, value: T) => void;
/**
* Filter with the provided predicate
* @param predicate The predicate function to filter the array.
* @returns void
*/
filter: (predicate: (value: T, index: number, array: T[]) => boolean, thisArg?: any) => void;
/**
* Concat the provided array to the end of the current array.
* @param array The array to concat.
* @returns void
*/
concat: (array: T[]) => void;
/**
* Merge the provided arrays into the current array.
* @param arrays The arrays to merge.
* @returns void
*/
merge: (...arrays: T[][]) => void;
/**
* Shift the first item from the array.
* @returns void
*/
shift: () => void;
/**
* Sort the array.
* @param compareFn The function to determine the order of the elements.
* @returns void
*/
sort: (compareFn?: (a: T, b: T) => number) => void;
}
/**
* A custom hook that provides comprehensive array state management with built-in manipulation methods.
*
* This hook offers a convenient way to manage array state with commonly needed operations
* like adding, removing, filtering, and sorting items. All operations return new arrays
* to maintain immutability and trigger React re-renders properly.
*
* @param initialValue - The initial array value to start with
* @returns An object containing the current array and methods to manipulate it
*
* @example
* ```tsx
* function TodoList() {
* const {
* array: todos,
* push,
* remove,
* clear,
* filter
* } = useArray([
* { id: 1, text: 'Learn React', done: false },
* { id: 2, text: 'Build something awesome', done: false }
* ])
*
* const addTodo = () => {
* push({
* id: Date.now(),
* text: 'New todo',
* done: false
* })
* }
*
* const removeTodo = (index) => {
* remove(index)
* }
*
* const clearCompleted = () => {
* filter(todo => !todo.done)
* }
*
* return (
* <div>
* <button onClick={addTodo}>Add Todo</button>
* <button onClick={clear}>Clear All</button>
* <button onClick={clearCompleted}>Clear Completed</button>
* {todos.map((todo, index) => (
* <div key={todo.id}>
* <span>{todo.text}</span>
* <button onClick={() => removeTodo(index)}>Remove</button>
* </div>
* ))}
* </div>
* )
* }
* ```
*/
declare function useArray<T>(initialValue: T[]): UseArrayReturn<T>;
/**
* A custom hook that returns the previous value of a state or prop.
* @param value The current value to track.
* @returns The previous value, first render is null.
*/
declare function usePrevious<TValue>(value: TValue): TValue | null;
type DefaultValue<S> = S | (() => S);
type NewState<S> = S | ((prev: S) => S);
interface UseStateWithHistoryHandlersReturn<S> {
/**
* History of state values.
*/
history: S[];
/**
* Pointer to the current history entry.
*/
pointer: number;
/**
* Go to a specific history entry.
* @param pointer The index of the history entry to go to.
*/
go: (pointer: number) => void;
/**
* Go back to the previous history entry.
*/
back: () => void;
/**
* Go forward to the next history entry.
*/
forward: () => void;
}
type UseStateWithHistoryReturn<S> = [
/**
* The current state value.
*/
value: S,
/**
* A function to update the state value.
*/
set: (newValue: NewState<S>) => void,
/**
* Handlers for navigating the history.
*/
handlers: UseStateWithHistoryHandlersReturn<S>
];
interface UseStateWithHistoryConfigParam {
/**
* The maximum number of history entries to keep.
* @default 10
*/
historyLimit?: number;
}
declare function useStateWithHistory<S = undefined>(initialState?: DefaultValue<S>, { historyLimit }?: UseStateWithHistoryConfigParam): UseStateWithHistoryReturn<S>;
type StorageValue<T> = T | undefined;
type UseStorageReturn<T> = [
/**
* The current stored value.
*/
value: StorageValue<T>,
/**
* A function to update the stored value.
*/
setValue: (value: T | ((prev: StorageValue<T>) => T)) => void,
/**
* A function to remove the stored value.
*/
remove: () => void
];
/**
* A custom hook that manages localStorage with React state synchronization.
* @param key - The localStorage key to store the value under.
* @param defaultValue - The default value to use if no stored value exists.
* @returns A tuple containing the current value, setter function, and remove function.
*/
declare function useLocalStorage<T = unknown>(key: string, defaultValue?: DefaultValue<T>): UseStorageReturn<T>;
/**
* A custom hook that manages sessionStorage with React state synchronization.
* @param key - The sessionStorage key to store the value under.
* @param defaultValue - The default value to use if no stored value exists.
* @returns A tuple containing the current value, setter function, and remove function.
*/
declare function useSessionStorage<T = unknown>(key: string, defaultValue?: DefaultValue<T>): UseStorageReturn<T>;
interface UseAsyncReturn<TValue, CError> {
/**
* The result of the async operation.
*/
value: TValue | null;
/**
* The error, if any, that occurred during the async operation.
*/
error: CError | null;
/**
* Whether the async operation is currently loading.
*/
loading: boolean;
/**
* A function to refresh the async operation.
*/
refresh: () => void;
/**
* A function to manually set the value.
*/
setValue: (value: TValue | null) => void;
}
/**
* A custom hook for handling asynchronous operations.
* @param cb - The async function to call.
* @param dependencies - The dependencies for the useEffect hook.
* @returns An object containing the result, error, and loading state.
*/
declare function useAsync<TValue, CError = Error>(cb: () => Promise<TValue>, dependencies?: DependencyList): UseAsyncReturn<TValue, CError>;
/**
* A custom hook for loading external scripts.
* @param url - The URL of the script to load.
*/
declare function useScript(url: string): UseAsyncReturn<unknown, Error>;
type EventKeysForTarget<T> = T extends Window ? keyof WindowEventMap : T extends Document ? keyof DocumentEventMap : T extends HTMLElement ? keyof HTMLElementEventMap : T extends MediaQueryList ? keyof MediaQueryListEventMap : T extends CookieStore ? keyof CookieStoreEventMap : string;
type EventForTargetAndKey<T, K> = T extends Window ? K extends keyof WindowEventMap ? WindowEventMap[K] : Event : T extends Document ? K extends keyof DocumentEventMap ? DocumentEventMap[K] : Event : T extends HTMLElement ? K extends keyof HTMLElementEventMap ? HTMLElementEventMap[K] : Event : T extends MediaQueryList ? K extends keyof MediaQueryListEventMap ? MediaQueryListEventMap[K] : Event : T extends CookieStore ? K extends keyof CookieStoreEventMap ? CookieStoreEventMap[K] : Event : Event;
type ListenerForTargetAndKey<T, K> = ((this: T, ev: EventForTargetAndKey<T, K>) => any) | {
handleEvent(ev: EventForTargetAndKey<T, K>): any;
};
/**
* A custom hook that adds an event listener to a target element.
* @param type The type of the event to listen for.
* @param listener The event listener function or object with handleEvent method.
* @param target The target element to attach the listener to (defaults to window).
* @param options Options for the event listener.
*/
declare function useEventListener<T extends EventTarget = Window, K extends EventKeysForTarget<T> = EventKeysForTarget<T>>(type: K, listener: ListenerForTargetAndKey<T, K>, target?: T, options?: boolean | AddEventListenerOptions): void;
interface WindowSize {
/**
* The width of the window.
*/
width: number;
/**
* The height of the window.
*/
height: number;
}
/**
* A custom hook that returns the current window size.
*/
declare function useWindowSize(): WindowSize;
/**
* A custom hook that listens for changes to a media query.
* @param query The media query string to match against.
* @returns A boolean indicating whether the media query matches the current viewport.
*/
declare function useMediaQuery(query: string): boolean;
interface UseGeolocationReturn {
/**
* Indicates if the geolocation data is being loaded.
*/
loading: boolean;
/**
* Indicates if there was an error retrieving the geolocation data.
*/
error: GeolocationPositionError | null;
/**
* The geolocation data retrieved from the browser.
*/
data: GeolocationCoordinates | null;
}
/**
* A custom hook that retrieves the user's geolocation.
* @param options Options for the geolocation request.
* @returns An object containing the loading state, error (if any), and the geolocation data.
*/
declare function useGeolocation(options?: PositionOptions): UseGeolocationReturn;
type UseStateWithValidationReturn<T> = [
/**
* The current state value.
*/
value: T,
/**
* A function to update the state value.
*/
setValue: (nextValue: NewState<T>) => void,
/**
* A boolean indicating whether the current state value is valid.
*/
isValid: boolean
];
/**
* A custom hook that manages state with validation.
* @param validationFn A function that validates the state.
* @param initialValue The initial state value.
* @returns An array containing the state value, a setter function, and a validity flag.
*/
declare function useStateWithValidation<T>(validationFn: (value: T) => boolean, initialValue: T): UseStateWithValidationReturn<T>;
type UseSizeReturn<TElement, HasExternalRef extends boolean> = HasExternalRef extends true ? {
/**
* The size of the element.
*/
size: DOMRectReadOnly;
} : {
/**
* The size of the element.
*/
size: DOMRectReadOnly;
/**
* A ref to the DOM element to measure.
*/
fromRef: React.RefObject<TElement | null>;
};
declare function useSize<TElement extends Element = Element>(): UseSizeReturn<TElement, false>;
declare function useSize<TElement extends Element = Element>(externalRef: React.RefObject<TElement | null>): UseSizeReturn<TElement, true>;
interface UseClickOutSideParams<TElement> {
/**
* A ref to the DOM element to detect outside clicks.
*/
externalRef?: React.RefObject<TElement>;
/**
* A callback function that is called when a click outside the element is detected.
* @param event The mouse event.
*/
onClickOutside: (event: MouseEvent) => void;
}
type UseClickOutSideReturn<TElement, HasExternalRef extends boolean> = HasExternalRef extends true ? void : {
/**
* A ref to the DOM element to measure.
*/
fromRef: React.RefObject<TElement | null>;
};
declare function useClickOutSide<TElement extends Element = Element>(params: Pick<UseClickOutSideParams<TElement>, 'onClickOutside'>): UseClickOutSideReturn<TElement, false>;
/**
* A custom hook that manages dark mode state.
* @param darkModeKey The key used to store the dark mode preference in local storage and the class name applied to the body element.
*/
declare function useDarkMode(darkModeKey?: string): (boolean | ((value: boolean | ((prev: boolean | undefined) => boolean)) => void))[];
type UseCopyToClipboardReturn = [
(text: string) => void,
{
value: string | null;
success: boolean | null;
error: DOMException | null;
isCopying: boolean;
}
];
/**
* A custom hook that provides a function to copy text to the clipboard.
* @returns An array containing the copy function and the current copy state.
*/
declare function useCopyToClipboard(): UseCopyToClipboardReturn;
type CookieInitWithoutName = Omit<CookieInit, 'name'>;
interface UseCookieInfoAndHandlersReturn {
/**
* Updates the cookie with the given value.
* @param value The new value for the cookie.
*/
updateCookie: (value: CookieInitWithoutName) => void;
/**
* Deletes the cookie.
*/
deleteCookie: () => void;
/**
* Indicates whether the cookie is being loaded.
*/
loadingCookie: boolean;
/**
* Indicates whether there was an error loading the cookie.
*/
errorLoadingCookie: DOMException | null;
/**
* Indicates whether the cookie action is being loaded.
*/
loadingCookieAction: boolean;
/**
* Indicates whether there was an error performing the cookie action.
*/
errorOnCookieAction: DOMException | null;
}
type UseCookieReturn = [CookieListItem | null, UseCookieInfoAndHandlersReturn];
/**
* Custom hook to manage a cookie.
* Internally uses the [CookieStore](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore) async API.
* @see https://developer.mozilla.org/en-US/docs/Web/API/CookieStore to know more about the API usage.
* @param cookieName The name of the cookie.
* @param defaultValue The default value for the cookie if it doesn't exist.
* @returns A tuple containing the cookie value and an object with cookie-related information and handlers.
*/
declare function useCookie(cookieName: string, defaultValue?: CookieInitWithoutName): UseCookieReturn;
type CookieChanges = Pick<CookieChangeEvent, 'changed' | 'deleted'>;
/**
* Custom hook to listen for cookie changes.
* @param onCookieChanges The callback to invoke when cookie changes are detected.
* @returns An object containing the current cookie changes.
*/
declare function useCookiesChangeListener(onCookieChanges: (e: CookieChangeEvent) => void): CookieChanges;
interface UseGetAllCookiesReturn {
/**
* Array with all current cookies
*/
cookies: CookieList | null;
/**
* Indicates whether the cookies are being loaded.
*/
loading: boolean;
/**
* Indicates whether there was an error loading the cookies.
*/
error: DOMException | null;
}
/**
* A hook to get all the current cookies using [CookieStore](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore) async API.
* @param params - parameters of the hook
* @returns current cookies
*/
declare function useGetAllCookies(params?: string | CookieStoreGetOptions): UseGetAllCookiesReturn;
/**
* A custom hook that returns the online status of the user.
*/
declare function useIsOnline(): boolean;
interface UseLongPressParams<T> {
/**
* A ref to the element to measure.
*/
externalRef?: React.RefObject<T>;
/**
* A callback function that is called when the long press is triggered.
*/
onLongPress: () => void;
/**
* The delay before the onLongPress callback is triggered.
*/
delay?: number;
}
type UseLongPressReturn<T, HasExternalRef extends boolean> = HasExternalRef extends true ? void : {
/**
* A ref to the element to measure.
*/
fromRef: React.RefObject<T>;
};
declare function useLongPress<TElement extends HTMLElement = HTMLElement>(params: Omit<UseLongPressParams<TElement>, 'externalRef'>): UseLongPressReturn<TElement, false>;
export { type UseAsyncReturn, type UseBroadcastChannelListenerParams, type UseBroadcastChannelSenderParams, type UseBroadcastChannelSenderReturn, type UseNearScreenParams, type UseStateWithHistoryReturn, type WindowSize, useArray, useAsync, useBoolean, useBroadcastChannelListener, useBroadcastChannelSender, useClickOutSide, useCookie, useCookiesChangeListener, useCopyToClipboard, useDarkMode, useDebouncedEffect, useDebouncedValue, useEffectAfterMount, useEventListener, useGeolocation, useGetAllCookies, useIsFirstRender, useIsOnline, useLocalStorage, useLongPress, useMediaQuery, useNearScreen, usePrevious, useScript, useSessionStorage, useSize, useStateWithHistory, useStateWithValidation, useTimeout, useWindowSize };