@supunlakmal/hooks
Version:
A collection of reusable React hooks
68 lines • 3.03 kB
JavaScript
import { useState, useCallback, useRef, useEffect } from 'react';
/**
* Hook to manage asynchronous operations that modify data (mutations).
* Handles loading, success, and error states, and provides callbacks.
*
* @param mutationFn The asynchronous function that performs the mutation.
* @param options Optional configuration with callbacks (onSuccess, onError, etc.).
* @returns State and functions to manage the mutation lifecycle.
*/
export const useMutation = (mutationFn, options) => {
const [status, setStatus] = useState('idle');
const [data, setData] = useState(undefined);
const [error, setError] = useState(undefined);
// Use refs for callbacks to avoid including them in the mutate callback dependencies
const optionsRef = useRef(options);
const mutationFnRef = useRef(mutationFn);
// Update refs if options change
useEffect(() => {
optionsRef.current = options;
}, [options]);
useEffect(() => {
mutationFnRef.current = mutationFn;
}, [mutationFn]);
const reset = useCallback(() => {
setStatus('idle');
setData(undefined);
setError(undefined);
}, []);
const mutateAsync = useCallback(async (variables) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
setStatus('loading');
setData(undefined);
setError(undefined);
(_b = (_a = optionsRef.current) === null || _a === void 0 ? void 0 : _a.onMutate) === null || _b === void 0 ? void 0 : _b.call(_a, variables);
try {
const result = await mutationFnRef.current(variables);
setData(result);
setStatus('success');
(_d = (_c = optionsRef.current) === null || _c === void 0 ? void 0 : _c.onSuccess) === null || _d === void 0 ? void 0 : _d.call(_c, result, variables);
(_f = (_e = optionsRef.current) === null || _e === void 0 ? void 0 : _e.onSettled) === null || _f === void 0 ? void 0 : _f.call(_e, result, undefined, variables);
return result;
}
catch (err) {
setError(err);
setStatus('error');
(_h = (_g = optionsRef.current) === null || _g === void 0 ? void 0 : _g.onError) === null || _h === void 0 ? void 0 : _h.call(_g, err, variables);
(_k = (_j = optionsRef.current) === null || _j === void 0 ? void 0 : _j.onSettled) === null || _k === void 0 ? void 0 : _k.call(_j, undefined, err, variables);
// Rethrow the error so callers of mutateAsync can catch it if needed
throw err;
}
}, []); // No dependencies needed due to refs
const mutate = useCallback((variables) => {
return mutateAsync(variables);
}, [mutateAsync]);
return {
status,
data,
error,
isLoading: status === 'loading',
isSuccess: status === 'success',
isError: status === 'error',
isIdle: status === 'idle',
mutate,
mutateAsync,
reset,
};
};
//# sourceMappingURL=useMutation.js.map