From a1afb6b599d91edc2531675044786af719e2f178 Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Thu, 17 Dec 2020 09:53:37 +0300 Subject: [PATCH] feat: add refetch function to hooks state Closes #22 --- src/endpoint.ts | 2 +- src/lazy-request-hook.ts | 26 +++++++++++++++++++++++--- src/reducer.ts | 26 +++++++++++++++++++------- target/endpoint.d.ts | 2 +- target/lazy-request-hook.d.ts | 6 +++++- target/lazy-request-hook.js | 12 ++++++++++-- target/reducer.d.ts | 5 +++-- target/request-hook.d.ts | 9 +-------- 8 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/endpoint.ts b/src/endpoint.ts index 8550238..70568b0 100644 --- a/src/endpoint.ts +++ b/src/endpoint.ts @@ -8,7 +8,7 @@ export enum Method { DELETE = 'DELETE', } -export type Endpoint = Readonly<{ +export type Endpoint = Readonly<{ method: Method; url: string | ((params: P) => string); headers?: Record; diff --git a/src/lazy-request-hook.ts b/src/lazy-request-hook.ts index 7c1b85b..c9c807d 100644 --- a/src/lazy-request-hook.ts +++ b/src/lazy-request-hook.ts @@ -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 = Readonly< export type RequestHandler = (config?: LazyRequestHandlerConfig) => Promise; +export type RefetchRequestHandler = () => void; + +export type PublicRequestStateWithRefetch = PublicRequestState & { refetch: RefetchRequestHandler }; + export function useLazyRequest< E extends Endpoint, R = ExtractEndpointResponse, @@ -31,7 +35,7 @@ export function useLazyRequest< >( endpoint: E, config?: LazyRequestConfig, -): [RequestHandler, PublicRequestState] { +): [RequestHandler, PublicRequestStateWithRefetch] { const [client] = useClient(); const { defaultHeaders } = useRequestContext(); const [state, dispatch] = React.useReducer, RequestAction>>( @@ -42,8 +46,9 @@ export function useLazyRequest< isCalled: false, } ); + const [prevHandlerConfig, setPrevHandlerConfig] = React.useState | 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({ ...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, }, ]; } diff --git a/src/reducer.ts b/src/reducer.ts index 1511acc..5607fcf 100644 --- a/src/reducer.ts +++ b/src/reducer.ts @@ -1,20 +1,32 @@ import { ClientResponse } from './client'; -export type RequestState = Readonly<{ +export type PublicRequestState = Readonly<{ data: R | null; loading: boolean; isCalled: boolean; +}>; + +export type RequestState = PublicRequestState & Readonly<{ prevHeaders?: Record; prevVariables?: Record; - prevParams?: Record + prevParams?: Record; }> -export type PublicRequestState = Pick, 'data' | 'loading' | 'isCalled'>; - export type RequestAction = - | { type: 'call', headers: Record, variables: Record, params?: Record } - | { type: 'success', response: ClientResponse } - | { type: 'failure', response: ClientResponse } + | { + type: 'call', + headers: Record, + variables: Record, + params?: Record + } + | { + type: 'success', + response: ClientResponse + } + | { + type: 'failure', + response: ClientResponse + } export function requestReducer(state: RequestState, action: RequestAction) { switch (action.type) { diff --git a/target/endpoint.d.ts b/target/endpoint.d.ts index 4996fea..3fb8732 100644 --- a/target/endpoint.d.ts +++ b/target/endpoint.d.ts @@ -6,7 +6,7 @@ export declare enum Method { PATCH = "PATCH", DELETE = "DELETE" } -export declare type Endpoint = Readonly<{ +export declare type Endpoint = Readonly<{ method: Method; url: string | ((params: P) => string); headers?: Record; diff --git a/target/lazy-request-hook.d.ts b/target/lazy-request-hook.d.ts index ad4b0f9..34e8248 100644 --- a/target/lazy-request-hook.d.ts +++ b/target/lazy-request-hook.d.ts @@ -12,4 +12,8 @@ export declare type LazyRequestHandlerConfig = Readonly; export declare type RequestHandler = (config?: LazyRequestHandlerConfig) => Promise; -export declare function useLazyRequest, R = ExtractEndpointResponse, V = ExtractEndpointVariables, P = ExtractEndpointParams>(endpoint: E, config?: LazyRequestConfig): [RequestHandler, PublicRequestState]; +export declare type RefetchRequestHandler = () => void; +export declare type PublicRequestStateWithRefetch = PublicRequestState & { + refetch: RefetchRequestHandler; +}; +export declare function useLazyRequest, R = ExtractEndpointResponse, V = ExtractEndpointVariables, P = ExtractEndpointParams>(endpoint: E, config?: LazyRequestConfig): [RequestHandler, PublicRequestStateWithRefetch]; diff --git a/target/lazy-request-hook.js b/target/lazy-request-hook.js index f8e58de..4de03b5 100644 --- a/target/lazy-request-hook.js +++ b/target/lazy-request-hook.js @@ -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, }, ]; } diff --git a/target/reducer.d.ts b/target/reducer.d.ts index 80bf787..0b0892f 100644 --- a/target/reducer.d.ts +++ b/target/reducer.d.ts @@ -1,13 +1,14 @@ import { ClientResponse } from './client'; -export declare type RequestState = Readonly<{ +export declare type PublicRequestState = Readonly<{ data: R | null; loading: boolean; isCalled: boolean; +}>; +export declare type RequestState = PublicRequestState & Readonly<{ prevHeaders?: Record; prevVariables?: Record; prevParams?: Record; }>; -export declare type PublicRequestState = Pick, 'data' | 'loading' | 'isCalled'>; export declare type RequestAction = { type: 'call'; headers: Record; diff --git a/target/request-hook.d.ts b/target/request-hook.d.ts index 8b372b0..0644b01 100644 --- a/target/request-hook.d.ts +++ b/target/request-hook.d.ts @@ -3,11 +3,4 @@ import { LazyRequestConfig } from './lazy-request-hook'; export declare type RequestConfig = Readonly & { skip?: boolean; }>; -export declare function useRequest, R = ExtractEndpointResponse, V = ExtractEndpointVariables, P = ExtractEndpointParams>(endpoint: E, config?: RequestConfig): Pick | undefined; - prevVariables?: Record | undefined; - prevParams?: Record | undefined; -}>, "loading" | "data" | "isCalled">; +export declare function useRequest, R = ExtractEndpointResponse, V = ExtractEndpointVariables, P = ExtractEndpointParams>(endpoint: E, config?: RequestConfig): import("./lazy-request-hook").PublicRequestStateWithRefetch;