UNPKG

@d3vtool/hooks

Version:

Collection of custom React hooks to simplify tasks in your React projects.

195 lines (194 loc) 8.72 kB
import { ms } from "../useDebounce"; /** * Type representing a function that initializes state. * @template T - The type of the state value. * @returns {T} - The initial state. */ export type StateInitializerAction<T> = () => T; /** * Type representing a function that updates the state based on the previous state. * @template T - The type of the state value. * @param {T} prev - The previous state value. * @returns {T} - The new state value. */ export type PrevStateAction<T> = (prev: T) => T; /** * Type representing a function that updates the state. * @template T - The type of the state value. * @param {T | PrevStateAction<T>} newState - The new state value or a function that computes the new state based on the previous state. */ export type UpdateStateAction<T> = (newState: T | PrevStateAction<T>) => void; /** * Type representing the return value of the `usePersistentState` hook. * It is a tuple where the first value is the current state and the second value is a function to update the state. * @template T - The type of the state value. */ export type UsePersistentState<T> = [T, UpdateStateAction<T>]; /** * A function type used for serializing a state value before storing it in persistent storage (e.g., `localStorage`). * * @template T - The type of the state value to be serialized. * * @param {T} data - The state value to be serialized. * @returns {string} - The serialized state value as a string. * * @example * // A custom serializer function that converts a `User` object to a string. * const serializeUser: SerializerFn<User> = (user) => user.name; * * // Usage of the custom serializer function * const serializedUser = serializeUser(new User('John Doe')); // Returns 'John Doe' */ export type SerializerFn<T> = (data: T) => string; /** * A function type used for deserializing a state value retrieved from persistent storage (e.g., `localStorage`). * * @template T - The type of the state value to be deserialized. * * @param {string} serialized - The serialized state value as a string. * @returns {T} - The deserialized state value. * * @example * // A custom deserializer function that converts a serialized string into a `User` object. * const deserializeUser: DeSerializerFn<User> = (data) => new User(data); * * // Usage of the custom deserializer function * const user = deserializeUser('John Doe'); // Returns a `User` object with the name 'John Doe' */ export type DeSerializerFn<T> = (serialized: string) => T; /** * Configuration options for `usePersistentState` to customize how the state * is saved, synchronized, and managed in localStorage. * * @template T - The type of the state being persisted. * * @property {number} [saveDelay=300] - Optional delay in milliseconds before saving the state to localStorage. * Helps debounce frequent state updates. * * @property {boolean} [clearStorageOnUnMount=false] - Whether the state should be cleared from localStorage when * the component unmounts. Defaults to `false`, meaning the state * will persist even after the component unmounts. * * @property {boolean} [useLayout=false] - Determines if the state update should be synchronized during the layout * phase using `useLayoutEffect`. Defaults to `false`, which means the state * updates will be handled asynchronously during the commit phase using `useEffect`. * * @property {SerializerFn<T>} [serialize] - Optional function for custom serialization of the state before storing it * in localStorage. By default, the state is serialized using JSON.stringify. * * @property {DeSerializerFn<T>} [deserialize] - Optional function for custom deserialization of the state when reading * it from localStorage. By default, the state is deserialized using * JSON.parse. */ export type UsePersistentStateConfig<T> = { saveDelay?: ms; clearStorageOnUnMount?: boolean; useLayout?: boolean; serialize?: SerializerFn<T>; deserialize?: DeSerializerFn<T>; }; /** * Represents the information of a specific item being stored in localStorage. * * @template T - The type of the value being stored. * * @property {string} key - The key used to identify the stored state in localStorage. * @property {T} value - The actual state value that is being persisted. */ export type StorageInfo<T> = { key: string; value: T; }; /** * Describes the structure of the broadcast event that is emitted to notify other browser * tabs about changes in the persistent state. * * @template T - The type of the state value being broadcasted. * * @property {"storage-broadcast"} type - The type of the event, indicating that the state has been broadcasted. * @property {StorageInfo<T>} storageData - The updated state information, including the key and the new value. */ export type StorageBroadcast<T> = { type: "storage-broadcast"; storageData: StorageInfo<T>; }; /** * A custom hook that persists state in `localStorage`, with configuration options to customize how the state is managed. * Supports debouncing state saving, clearing the state on unmount, and synchronizing state updates during the layout phase. * * @template T - The type of the state value. Defaults to `unknown` if not provided. * * @param {string} key - The key under which the state is stored in `localStorage`. * @param {T | StateInitializerAction<T>} initialState - The initial state value or a function that returns the initial state. * @param {UsePersistentStateConfig<T>} [config] - Optional configuration to customize how the state is managed: * - `saveDelay` (default 300ms): Delay before saving the state to `localStorage`. * - `clearStorageOnUnMount` (default `false`): Whether to clear the state from `localStorage` when the component unmounts. * - `useLayout` (default `false`): If `true`, updates the state during the layout phase for immediate rendering. * - `serialize`: A custom serialization function to transform the state before saving it. * - `deserialize`: A custom deserialization function to transform the state when reading it from storage. * * @returns {UsePersistentState<T>} - The current state and a function to update it. * * @example * // Basic usage with a simple value: * const [count, setCount] = usePersistentState('count', 0); * * // Using a function for the initial state: * const [user, setUser] = usePersistentState('user', () => ({ name: 'John Doe' })); * * // Updating the state: * setCount(5); * * // Updating based on the previous state: * setCount(prev => prev + 1); * * @example * // Example 1: Using `usePersistentState` with the `saveDelay` config: * const [user, setUser] = usePersistentState('user', { name: 'Jane' }, { saveDelay: 500 }); * * // State will be saved with a 500ms delay to debounce frequent updates. * setUser({ name: 'John' }); * * @example * // Example 2: Using `usePersistentState` with `clearStorageOnUnMount` config: * const config = useMemo(() => ({ * clearStorageOnUnMount: true * }), []); * * const [sessionData, setSessionData] = usePersistentState('session', {}, config); * * // When the component unmounts, the session data will be removed from `localStorage`. * * @example * // Example 3: Using `usePersistentState` with `useLayout` config: * const [layoutData, setLayoutData] = usePersistentState('layoutData', { theme: 'light' }, { * useLayout: true * }); * * // State updates will happen synchronously during the layout phase, ensuring immediate updates. * setLayoutData({ theme: 'dark' }); * * @example * // Example 4: Using `usePersistentState` with custom serialization and deserialization: * class User { * constructor(public name: string) {} * * static serialize(user: User): string { * return user.name; * } * * static deserialize(data: string): User { * return new User(data); * } * } * * const config = useMemo(() => ({ * serialize: User.serialize, * deserialize: User.deserialize * }), []); * * const [user, setUser] = usePersistentState('user', new User('Alice'), config); * * // Using custom serializer and deserializer to store and retrieve a `User` object. */ export declare function usePersistentState<T = unknown>(key: string, initialState: T | StateInitializerAction<T>, config?: UsePersistentStateConfig<T>): UsePersistentState<T>;