turash/bugulma/frontend/hooks/useAction.ts
Damir Mukimov 6347f42e20
Consolidate repositories: Remove nested frontend .git and merge into main repository
- Remove nested git repository from bugulma/frontend/.git
- Add all frontend files to main repository tracking
- Convert from separate frontend/backend repos to unified monorepo
- Preserve all frontend code and development history as tracked files
- Eliminate nested repository complexity for simpler development workflow

This creates a proper monorepo structure with frontend and backend
coexisting in the same repository for easier development and deployment.
2025-11-25 06:02:57 +01:00

54 lines
1.6 KiB
TypeScript

import { useState, useCallback } from 'react';
type ActionState<T> = {
data: T | null;
error: string | null;
isPending: boolean;
};
/**
* A reusable hook for managing asynchronous operations.
* It provides a clean API for handling pending, success (data), and error states
* using a traditional useState/useCallback pattern for maximum compatibility and stability.
*
* @template T The expected data type of the action's successful result.
* @template A The arguments tuple type for the action.
* @param action The asynchronous function to execute.
* @returns An object containing the action's state (`data`, `error`), pending status (`isPending`), an `execute` function, and a `reset` function.
*/
export function useAction<T, A extends unknown[]>(action: (...args: A) => Promise<T>) {
const [state, setState] = useState<ActionState<T>>({
data: null,
error: null,
isPending: false,
});
const execute = useCallback(
async (payload: A) => {
setState({ data: null, error: null, isPending: true });
try {
const data = await action(...payload);
setState({ data, error: null, isPending: false });
return { data };
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred.';
setState({ data: null, error: errorMessage, isPending: false });
return { error: errorMessage };
}
},
[action]
);
const reset = useCallback(() => {
setState({ data: null, error: null, isPending: false });
}, []);
return {
data: state.data,
error: state.error,
isPending: state.isPending,
execute,
reset,
};
}