feat: add refetch function to hooks state

Closes #22
This commit is contained in:
Dmitriy Pleshevskiy 2020-12-17 09:53:37 +03:00
parent d4e83748c3
commit a1afb6b599
8 changed files with 63 additions and 25 deletions

View File

@ -8,7 +8,7 @@ export enum Method {
DELETE = 'DELETE',
}
export type Endpoint<R, V, P = never> = Readonly<{
export type Endpoint<R, _V, P = never> = Readonly<{
method: Method;
url: string | ((params: P) => string);
headers?: Record<string, string>;

View File

@ -1,4 +1,4 @@
import React, { useCallback, useMemo } from 'react';
import React from 'react';
import invariant from 'tiny-invariant';
import isEqual from 'lodash.isequal';
import { useClient } from './client-hook';
@ -23,6 +23,10 @@ export type LazyRequestHandlerConfig<R, V, P> = Readonly<
export type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
export type RefetchRequestHandler = () => void;
export type PublicRequestStateWithRefetch<R> = PublicRequestState<R> & { refetch: RefetchRequestHandler };
export function useLazyRequest<
E extends Endpoint<R, V, P>,
R = ExtractEndpointResponse<E>,
@ -31,7 +35,7 @@ export function useLazyRequest<
>(
endpoint: E,
config?: LazyRequestConfig<R, V, P>,
): [RequestHandler<R, V, P>, PublicRequestState<R>] {
): [RequestHandler<R, V, P>, PublicRequestStateWithRefetch<R>] {
const [client] = useClient();
const { defaultHeaders } = useRequestContext();
const [state, dispatch] = React.useReducer<React.Reducer<RequestState<R>, RequestAction<R>>>(
@ -42,8 +46,9 @@ export function useLazyRequest<
isCalled: false,
}
);
const [prevHandlerConfig, setPrevHandlerConfig] = React.useState<LazyRequestHandlerConfig<R, V, P> | null>(null);
const transformResponseData = useCallback(
const transformResponseData = React.useCallback(
(data: unknown): R => {
return isFunction(endpoint.transformResponseData) ?
endpoint.transformResponseData(data)
@ -98,6 +103,8 @@ export function useLazyRequest<
dispatch({ type: 'call', headers, variables, params });
setPrevHandlerConfig(handlerConfig ?? {});
return client
.request<R>({
...endpoint,
@ -128,12 +135,25 @@ export function useLazyRequest<
[state, config, client, endpoint, defaultHeaders, transformResponseData]
);
const refetch = React.useCallback(
() => {
if (prevHandlerConfig != null) {
handler({
...prevHandlerConfig,
force: true,
});
}
},
[handler, prevHandlerConfig]
);
return [
handler,
{
data: state.data,
loading: state.loading,
isCalled: state.isCalled,
refetch,
},
];
}

View File

@ -1,20 +1,32 @@
import { ClientResponse } from './client';
export type RequestState<R> = Readonly<{
export type PublicRequestState<R> = Readonly<{
data: R | null;
loading: boolean;
isCalled: boolean;
}>;
export type RequestState<R> = PublicRequestState<R> & Readonly<{
prevHeaders?: Record<string, string>;
prevVariables?: Record<string, any>;
prevParams?: Record<string, any>
prevParams?: Record<string, any>;
}>
export type PublicRequestState<R> = Pick<RequestState<R>, 'data' | 'loading' | 'isCalled'>;
export type RequestAction<R> =
| { type: 'call', headers: Record<string, string>, variables: Record<string, any>, params?: Record<string, any> }
| { type: 'success', response: ClientResponse<R> }
| { type: 'failure', response: ClientResponse<R> }
| {
type: 'call',
headers: Record<string, string>,
variables: Record<string, any>,
params?: Record<string, any>
}
| {
type: 'success',
response: ClientResponse<R>
}
| {
type: 'failure',
response: ClientResponse<R>
}
export function requestReducer<R>(state: RequestState<R>, action: RequestAction<R>) {
switch (action.type) {

View File

@ -6,7 +6,7 @@ export declare enum Method {
PATCH = "PATCH",
DELETE = "DELETE"
}
export declare type Endpoint<R, V, P = never> = Readonly<{
export declare type Endpoint<R, _V, P = never> = Readonly<{
method: Method;
url: string | ((params: P) => string);
headers?: Record<string, string>;

View File

@ -12,4 +12,8 @@ export declare type LazyRequestHandlerConfig<R, V, P> = Readonly<LazyRequestConf
force?: boolean;
}>;
export declare type RequestHandler<R, V, P> = (config?: LazyRequestHandlerConfig<R, V, P>) => Promise<R | null>;
export declare function useLazyRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: LazyRequestConfig<R, V, P>): [RequestHandler<R, V, P>, PublicRequestState<R>];
export declare type RefetchRequestHandler = () => void;
export declare type PublicRequestStateWithRefetch<R> = PublicRequestState<R> & {
refetch: RefetchRequestHandler;
};
export declare function useLazyRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: LazyRequestConfig<R, V, P>): [RequestHandler<R, V, P>, PublicRequestStateWithRefetch<R>];

View File

@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React from 'react';
import invariant from 'tiny-invariant';
import isEqual from 'lodash.isequal';
import { useClient } from './client-hook';
@ -13,7 +13,8 @@ export function useLazyRequest(endpoint, config) {
loading: false,
isCalled: false,
});
const transformResponseData = useCallback((data) => {
const [prevHandlerConfig, setPrevHandlerConfig] = React.useState(null);
const transformResponseData = React.useCallback((data) => {
return isFunction(endpoint.transformResponseData) ?
endpoint.transformResponseData(data)
: data;
@ -46,6 +47,7 @@ export function useLazyRequest(endpoint, config) {
const onComplete = (_b = handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.onComplete) !== null && _b !== void 0 ? _b : config === null || config === void 0 ? void 0 : config.onComplete;
const onFailure = (_c = handlerConfig === null || handlerConfig === void 0 ? void 0 : handlerConfig.onFailure) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config.onFailure;
dispatch({ type: 'call', headers, variables, params });
setPrevHandlerConfig(handlerConfig !== null && handlerConfig !== void 0 ? handlerConfig : {});
return client
.request(Object.assign(Object.assign({}, endpoint), { url: endpointUrl, headers,
variables,
@ -64,12 +66,18 @@ export function useLazyRequest(endpoint, config) {
return null;
});
}, [state, config, client, endpoint, defaultHeaders, transformResponseData]);
const refetch = React.useCallback(() => {
if (prevHandlerConfig != null) {
handler(Object.assign(Object.assign({}, prevHandlerConfig), { force: true }));
}
}, [handler, prevHandlerConfig]);
return [
handler,
{
data: state.data,
loading: state.loading,
isCalled: state.isCalled,
refetch,
},
];
}

5
target/reducer.d.ts vendored
View File

@ -1,13 +1,14 @@
import { ClientResponse } from './client';
export declare type RequestState<R> = Readonly<{
export declare type PublicRequestState<R> = Readonly<{
data: R | null;
loading: boolean;
isCalled: boolean;
}>;
export declare type RequestState<R> = PublicRequestState<R> & Readonly<{
prevHeaders?: Record<string, string>;
prevVariables?: Record<string, any>;
prevParams?: Record<string, any>;
}>;
export declare type PublicRequestState<R> = Pick<RequestState<R>, 'data' | 'loading' | 'isCalled'>;
export declare type RequestAction<R> = {
type: 'call';
headers: Record<string, string>;

View File

@ -3,11 +3,4 @@ import { LazyRequestConfig } from './lazy-request-hook';
export declare type RequestConfig<R, V, P> = Readonly<LazyRequestConfig<R, V, P> & {
skip?: boolean;
}>;
export declare function useRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: RequestConfig<R, V, P>): Pick<Readonly<{
data: R | null;
loading: boolean;
isCalled: boolean;
prevHeaders?: Record<string, string> | undefined;
prevVariables?: Record<string, any> | undefined;
prevParams?: Record<string, any> | undefined;
}>, "loading" | "data" | "isCalled">;
export declare function useRequest<E extends Endpoint<R, V, P>, R = ExtractEndpointResponse<E>, V = ExtractEndpointVariables<E>, P = ExtractEndpointParams<E>>(endpoint: E, config?: RequestConfig<R, V, P>): import("./lazy-request-hook").PublicRequestStateWithRefetch<R>;