This repository has been archived on 2023-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
react-rest-request/target/lazy_request_hook.js

97 lines
5 KiB
JavaScript
Raw Normal View History

2021-06-15 00:11:58 +03:00
import React from 'react';
import invariant from 'tiny-invariant';
import isEqual from 'lodash.isequal';
import { useClient } from './client_hook';
2021-06-23 02:30:19 +03:00
import { methodWithoutEffects } from './endpoint';
import { INITIAL_REQUEST_STATE, requestReducer } from './reducer';
2021-06-15 00:11:58 +03:00
import { useRequestContext } from './request_context';
import { isFunction } from './misc';
2021-06-23 02:30:19 +03:00
;
2021-06-15 00:11:58 +03:00
export function useLazyRequest(endpoint, config) {
const [client] = useClient();
const { defaultHeaders } = useRequestContext();
2021-06-23 02:30:19 +03:00
const [state, dispatch] = React.useReducer(requestReducer, INITIAL_REQUEST_STATE);
2021-06-15 00:11:58 +03:00
const [prevHandlerConfig, setPrevHandlerConfig] = React.useState(null);
const abortControllerRef = React.useRef(new AbortController());
2021-06-15 00:11:58 +03:00
const transformResponseData = React.useCallback((data) => {
return isFunction(endpoint.transformResponseData) ?
endpoint.transformResponseData(data)
: data;
}, [endpoint]);
const handler = React.useCallback((handlerConfig) => {
2021-06-17 22:43:29 +03:00
var _a;
2021-06-15 00:11:58 +03:00
if ((state === null || state === void 0 ? void 0 : state.loading) || (state === null || state === void 0 ? void 0 : state.isCanceled)) {
return Promise.resolve(null);
}
let params;
let endpointUrl;
let isSameRequest = true;
if (isFunction(endpoint.url)) {
params = (_a = handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.params) !== null && _a !== void 0 ? _a : config === null || config === void 0 ? void 0 : config.params;
invariant(params, 'Endpoint required params');
endpointUrl = endpoint.url(params);
isSameRequest = !!(state === null || state === void 0 ? void 0 : state.prevParams) && isEqual(state.prevParams, params);
}
else {
endpointUrl = endpoint.url;
}
const variables = Object.assign(Object.assign({}, config === null || config === void 0 ? void 0 : config.variables), handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.variables);
const headers = Object.assign(Object.assign(Object.assign(Object.assign({}, defaultHeaders), endpoint.headers), config === null || config === void 0 ? void 0 : config.headers), handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.headers);
2021-06-23 02:30:19 +03:00
const shouldReturnCachedValue = (methodWithoutEffects(endpoint.method)
&& state.isCalled
2021-06-15 00:11:58 +03:00
&& isSameRequest
&& (state === null || state === void 0 ? void 0 : state.prevVariables) && isEqual(state.prevVariables, variables)
&& (state === null || state === void 0 ? void 0 : state.prevHeaders) && isEqual(state.prevHeaders, headers)
2021-06-23 02:30:19 +03:00
&& !(handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.force));
if (shouldReturnCachedValue) {
2021-06-15 00:11:58 +03:00
return Promise.resolve(state.data);
}
2021-06-17 22:43:29 +03:00
const onCompletes = [config === null || config === void 0 ? void 0 : config.onComplete, handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.onComplete].filter(isFunction);
const onFailures = [config === null || config === void 0 ? void 0 : config.onFailure, handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.onFailure].filter(isFunction);
2021-06-15 00:11:58 +03:00
dispatch({ type: 'call', headers, variables, params });
setPrevHandlerConfig(handlerConfig !== null && handlerConfig !== void 0 ? handlerConfig : {});
return client
.request(Object.assign(Object.assign({}, endpoint), { abortSignal: abortControllerRef.current.signal, url: endpointUrl, headers,
2021-06-15 00:11:58 +03:00
variables,
transformResponseData }))
.then((response) => {
dispatch({ type: 'success', response });
2021-06-17 22:43:29 +03:00
onCompletes.forEach(cb => cb(response.data));
2021-06-15 00:11:58 +03:00
return response.data;
}, (response) => {
dispatch({ type: 'failure', response });
2021-06-17 22:43:29 +03:00
if (!response.canceled) {
onFailures.forEach(cb => cb(response));
2021-06-15 00:11:58 +03:00
}
return null;
});
}, [state, config, client, endpoint, defaultHeaders, transformResponseData]);
const refetchRequest = React.useCallback(() => {
2021-06-15 00:11:58 +03:00
if (prevHandlerConfig != null) {
2021-06-23 02:30:19 +03:00
handler(Object.assign({}, prevHandlerConfig));
2021-06-15 00:11:58 +03:00
}
}, [handler, prevHandlerConfig]);
const cancelRequest = React.useCallback(() => {
dispatch({ type: 'cancel' });
abortControllerRef.current.abort();
abortControllerRef.current = new AbortController();
}, []);
2021-06-23 02:30:19 +03:00
const clearRequestStore = React.useCallback(() => {
dispatch({ type: 'clearStore' });
}, []);
React.useEffect(() => cancelRequest, [cancelRequest]);
2021-06-15 00:11:58 +03:00
return [
handler,
{
data: state.data,
loading: state.loading,
isCalled: state.isCalled,
isCanceled: state.isCanceled,
2021-06-17 22:43:29 +03:00
fetchError: state.fetchError,
refetch: refetchRequest,
cancel: cancelRequest,
2021-06-23 02:30:19 +03:00
clearStore: clearRequestStore
2021-06-15 00:11:58 +03:00
},
];
}