@d3vtool/hooks
Version:
Collection of custom React hooks to simplify tasks in your React projects.
210 lines (209 loc) • 9.35 kB
TypeScript
import { PromiseHubError, PromiseHub } from ".";
/**
* A type representing the function to re-run the promise action.
*
* @template R - The type of the resolved value from the promise.
* @returns {Promise<R | undefined>} - A promise that resolves with the updated state or `undefined` if the promise fails.
*/
export type ReAction<R> = () => Promise<R | undefined>;
/**
* A type representing the action that performs an asynchronous operation to update the state.
*
* @template R - The type of the state being managed by the promise action.
* @param {R} prevState - The previous state before the promise action runs.
* @returns {Promise<R>} - A promise that resolves with the new state after the async operation.
*/
export type PromiseAction<R> = (prevState: R) => Promise<R>;
export type ResolveAction = (value?: unknown) => void;
/**
* A type representing the structure returned by the `usePromiseHub` hook.
*
* @template R - The type of the state being managed by the promise hub.
* @template E - The type of the error object if the promise action fails.
*
* @type {Object} - Returns an object with the following properties:
* - `data`: The current state managed by the promise hub.
* - `error`: An object representing any error encountered during the promise execution.
* - `isPending`: A boolean flag indicating whether the promise action is still running (loading state).
* - `reAction`: A function that can be called to manually trigger the promise action and update the state.
*/
export type UsePromiseHub<R, E> = {
data: R;
error: PromiseHubError<E>;
isPending: boolean;
reAction: ReAction<R>;
};
/**
* Configuration options for the `usePromiseHub` hook.
*
* @type {Object} - Defines the configuration for managing the asynchronous state.
* - `immediate`: If `true`, the promise action will be triggered immediately upon hook initialization.
* - `suspense`: If `true`, integrates with React Suspense, suspending the component until the promise resolves.
*/
export type UsePromiseHubConfig = {
immediate?: boolean;
suspense?: boolean;
};
/**
* A hook that provides an easy way to manage asynchronous state using a promise-based hub.
* It returns the current state, any errors, loading state, and a function to manually trigger the promise.
*
* @template R - The type of the state managed by the promise hub.
* @template E - The type of the error object, defaults to `Error`.
*
* @param {PromiseHub<R, E>} promiseHub - The promise hub managing the async state.
* @param {UsePromiseHubConfig} [config={immediate: true, suspense: false}] - Configuration options for the hook.
*
* @returns {UsePromiseHub<R, E>} - Returns an object containing:
* - `data`: The current state managed by the promise hub.
* - `error`: The error object if the promise fails.
* - `isPending`: A boolean indicating whether the promise is in progress (loading).
* - `reAction`: A function that can be used to manually trigger the promise action and update the state.
*
* @example
* // Example usage of `usePromiseHub` with immediate execution and retry functionality:
* const { data, error, isPending, reAction } = usePromiseHub(fetchUserDataHub, { immediate: true });
*
* return (
* <div>
* {isPending ? <p>Loading...</p> : <p>{data}</p>}
* {error && <p>Error: {error.message}</p>}
* <button onClick={reAction} disabled={isPending}>Retry</button>
* </div>
* );
*
* @example
* // Example usage with Suspense behavior enabled:
* const { data, error, reAction } = usePromiseHub(fetchUserDataHub, { immediate: true, suspense: true });
*
* return (
* <Suspense fallback={<p>Loading...</p>}>
* {data?.user}
* {error && <p>Error: {error.message}</p>}
* </Suspense>
* );
*/
export declare function usePromiseHub<R, E = Error>(promiseHub: PromiseHub<R, E>, config?: UsePromiseHubConfig): UsePromiseHub<R, E>;
/**
* A type representing the structure returned by the `usePromiseReadHub` hook.
*
* @template R - The type of the state managed by the promise hub.
* @template E - The type of the error object if the promise action fails.
*
* @type {Object} - Returns an object with the following properties:
* - `data`: The current state managed by the promise hub.
* - `error`: An object representing any error encountered during the promise execution.
* - `isPending`: A boolean flag indicating whether the promise action is still running (loading state).
*/
export type UsePromiseReadHub<R, E> = {
data: R;
error: PromiseHubError<E>;
isPending: boolean;
};
/**
* A hook that provides read-only access to the state managed by a promise hub.
* It returns the current state, any error state, and a loading flag indicating the promise's execution status.
*
* @template R - The type of the state managed by the promise hub.
* @template E - The type of the error object, defaults to `Error`.
*
* @param {PromiseHub<R, E>} promiseHub - The promise hub managing the async state.
* @param {boolean} [suspense=false] - If `true`, integrates with React Suspense, suspending the component until the promise resolves.
*
* @returns {UsePromiseReadHub<R, E>} - Returns an object containing:
* - `data`: The current state managed by the promise hub.
* - `error`: The error object if the promise failed.
* - `isPending`: A boolean indicating whether the promise is in progress (loading state).
*
* @example
* // Example usage of `usePromiseReadHub`:
* const { data, error, isPending } = usePromiseReadHub(fetchUserDataHub);
*
* // Render the state
* return (
* <div>
* {isPending ? <p>Loading...</p> : <p>{data}</p>}
* {error && <p>Error: {error.message}</p>}
* </div>
* );
*
* @example
* // Example usage with Suspense behavior enabled:
* const { data, error } = usePromiseReadHub(fetchUserDataHub, true);
*
* return (
* <Suspense fallback={<p>Loading...</p>}>
* <p>{data?.user}</p>
* {error && <p>Error: {error.message}</p>}
* </Suspense>
* );
*/
export declare function usePromiseReadHub<R, E = Error>(promiseHub: PromiseHub<R, E>, suspense?: boolean): UsePromiseReadHub<R, E>;
export type UsePromiseHubAction<R, E> = {
reAction: ReAction<R>;
error: PromiseHubError<E>;
isPending: boolean;
};
/**
* A custom hook that provides access to the `reAction` function from a given PromiseHub,
* along with the current error state and loading status.
*
* The `reAction` function allows you to manually trigger the asynchronous action defined within the hub.
* This is useful when you want to re-trigger a specific action (e.g., fetching data) based on some user interaction.
*
* @template R - The type of the state managed by the promise hub.
* @template E - The type of error that might be encountered during the promise execution, defaulting to `Error`.
*
* @param {PromiseHub<R, E>} promiseHub - The promise hub managing the asynchronous state.
* @param {boolean} [suspense=false] - If `true`, the hook will suspend rendering while the promise is pending.
*
* @returns {UsePromiseHubAction<R, E>} - Returns an object containing:
* - `reAction`: A function to manually trigger the asynchronous action.
* - `error`: The current error state (if the promise failed).
* - `isPending`: A boolean flag indicating whether the asynchronous action is still in progress.
*
* @example
* // Example usage of `usePromiseHubAction` for manually refetching data:
* const { reAction: refetchProducts, error, isPending } = usePromiseHubAction(productListHub);
*
* return (
* <div>
* <button onClick={refetchProducts} disabled={isPending}>
* {isPending ? 'Loading...' : 'Refetch Products'}
* </button>
* {error && <p style={{ color: 'red' }}>Error fetching products: {error.message}</p>}
* </div>
* );
*
* // In this example:
* // - `refetchProducts` is the function that re-triggers the data fetching logic in the `productListHub`.
* // - The button is disabled and displays "Loading..." while the action is in progress.
* // - If the action fails, an error message is displayed below the button.
*
* @example
* // Example usage of `usePromiseHubAction` with suspense enabled:
* // The Suspense boundary will wait for the promise to resolve before rendering the component.
* import React, { Suspense } from "react";
*
* const ProductList: React.FC = () => {
* const { reAction: refetchProducts, error, isPending } = usePromiseHubAction(productListHub, true);
*
* return (
* <Suspense fallback={<p>Loading products...</p>}>
* <div>
* <button onClick={refetchProducts} disabled={isPending}>
* {isPending ? 'Loading...' : 'Refetch Products'}
* </button>
* {error && <p style={{ color: 'red' }}>Error fetching products: {error.message}</p>}
* </div>
* </Suspense>
* );
* };
*
* // In this example:
* // - `Suspense` wraps the component to handle the loading state while the promise action is pending.
* // - If `suspense` is set to `true`, the component will suspend until the asynchronous action is completed.
* // - The `fallback` prop in `Suspense` will show the loading text until the promise resolves.
*
*/
export declare function usePromiseHubAction<R, E = Error>(promiseHub: PromiseHub<R>, suspense?: boolean): UsePromiseHubAction<R, E>;