UNPKG

synapse-storage

Version:

Набор инструментов для управления состоянием и апи-запросами

85 lines (80 loc) 2.89 kB
import { useCallback, useEffect, useRef, useState } from "react"; const IDLE_STATE = { status: 'idle', data: undefined, error: undefined }; /** * Хук для выполнения мутаций (POST/PUT/DELETE/PATCH) через эндпоинт ApiClient. * * В отличие от {@link useApiQuery}, запрос не стартует автоматически — его * запускает `mutate`/`mutateAsync`. Мутации не кэшируются (по REST-методу), а их * `invalidatesTags` инвалидируют кэш — активные `useApiQuery` соседних эндпоинтов * автоматически перезапросятся через шину инвалидации. * * @example * const { mutate, isLoading } = useApiMutation(endpoints.createUser) * mutate({ name: 'Alex' }) */ function useApiMutation(endpoint, options = {}) { const optionsRef = useRef(options); optionsRef.current = options; const [state, setState] = useState(IDLE_STATE); const reqRef = useRef(null); const mountedRef = useRef(true); useEffect(()=>{ mountedRef.current = true; return ()=>{ mountedRef.current = false; reqRef.current?.abort(); }; }, []); const mutateAsync = useCallback(async (params)=>{ setState({ status: 'loading', data: undefined, error: undefined }); const req = endpoint.request(params, optionsRef.current); reqRef.current = req; try { const res = await req.wait(); // wait() реджектится на !ok, но подстрахуемся if (!res.ok) throw res.error ?? new Error('Mutation failed'); if (mountedRef.current) setState({ status: 'success', data: res.data, error: undefined }); return res; } catch (err) { if (mountedRef.current) setState({ status: 'error', data: undefined, error: err }); throw err; } }, [ endpoint ]); const mutate = useCallback((params)=>{ // Намеренно глотаем reject — состояние ошибки уже выставлено в mutateAsync mutateAsync(params).catch(()=>{}); }, [ mutateAsync ]); const reset = useCallback(()=>setState(IDLE_STATE), []); return { mutate, mutateAsync, data: state.data, error: state.error, status: state.status, isLoading: state.status === 'loading', isError: state.status === 'error', isSuccess: state.status === 'success', reset }; } export { useApiMutation }; //# sourceMappingURL=useApiMutation.js.map