From 1ca1bc46302cc6b834b1907a9e5001c33ba7ef70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon?= Date: Mon, 27 May 2024 11:46:53 +0200 Subject: [PATCH] version: 1.0.6 Fixes an issue (#18) with extending config, refactoring of code --- package.json | 2 +- src/createLoader.ts | 50 +++++-- src/createQuery.ts | 145 +++++++++---------- src/index.ts | 24 +-- testing-app/src/components/ErrorBoundary.tsx | 38 +++++ testing-app/src/tests.test.tsx | 40 +---- 6 files changed, 164 insertions(+), 135 deletions(-) create mode 100644 testing-app/src/components/ErrorBoundary.tsx diff --git a/package.json b/package.json index d763f2f..feb7597 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ryfylke-react/rtk-query-loader", - "version": "1.0.5", + "version": "1.0.6", "description": "Lets you create reusable, extendable RTK loaders for React components.", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", diff --git a/src/createLoader.ts b/src/createLoader.ts index 6e001ef..d9cdcbd 100644 --- a/src/createLoader.ts +++ b/src/createLoader.ts @@ -52,6 +52,7 @@ export const createUseLoader = < ) : []; const aggregatedQuery = aggregateToQuery(queriesList); + if (createUseLoaderArgs.config?.deferred?.shouldThrowError) { if (loaderRes.deferredQueries) { const deferredQueriesList = Object.keys( @@ -60,6 +61,7 @@ export const createUseLoader = < (key) => (loaderRes.deferredQueries as TDeferred)[key] ); if (deferredQueriesList.some((q) => q.isError)) { + aggregatedQuery.isSuccess = false; aggregatedQuery.isError = true; aggregatedQuery.error = deferredQueriesList.find( (q) => q.isError @@ -173,7 +175,7 @@ export const createLoader = < >({ useQueries, transform, - ...loaderArgs + ...extendedArgs }: Partial< Types.CreateLoaderArgs< E_TProps, @@ -194,17 +196,14 @@ export const createLoader = < >; const mergedConfig = mergeConfig( original.config ?? {}, - loaderArgs.config ?? {} + extendedArgs.config ?? {} + ); + + backwardsSupportLoaderComponent( + mergedConfig, + extendedArgs ); - // For backwards support of `loaderComponent - if ( - !mergedConfig.loaderComponent && - loaderArgs.loaderComponent - ) { - mergedConfig.loaderComponent = - loaderArgs.loaderComponent; - } const extendedLoader: Types.Loader< E_TProps, E_TReturn, @@ -214,7 +213,7 @@ export const createLoader = < E_TArg > = { ...original, - ...loaderArgs, + ...extendedArgs, config: mergedConfig, }; @@ -233,6 +232,15 @@ export const createLoader = < config: mergedConfig, }); extendedLoader.useLoader = newUseLoader; + } else if (extendedArgs.config) { + const newUseLoader = createUseLoader({ + useQueries: + extendedLoader.useLoader.original_args.useQueries, + transform: + extendedLoader.useLoader.original_args.transform, + config: mergedConfig, + }); + extendedLoader.useLoader = newUseLoader; } return extendedLoader; @@ -241,3 +249,23 @@ export const createLoader = < return loader; }; + +function backwardsSupportLoaderComponent( + mergedConfig: Types.LoaderConfig, + extendedArgs: Types.CreateLoaderArgs< + any, + any, + any, + any, + any, + any + > +) { + if ( + !mergedConfig.loaderComponent && + extendedArgs.loaderComponent + ) { + mergedConfig.loaderComponent = extendedArgs.loaderComponent; + } + return mergedConfig; +} diff --git a/src/createQuery.ts b/src/createQuery.ts index 83df0b6..bfe0a52 100644 --- a/src/createQuery.ts +++ b/src/createQuery.ts @@ -26,78 +26,22 @@ export const useCreateQuery = ( ): Types.UseQueryResult => { const safeDependencies = dependencies ?? []; const requestId = R.useRef(requestIdGenerator()).current; - const [state, dispatch] = R.useReducer( - ( - state: Types.UseQueryResult, - action: Types.CreateQueryReducerAction - ) => { - switch (action.type) { - case "load": - return { - ...state, - isSuccess: false, - isError: false, - isFetching: false, - isLoading: true, - isUninitialized: false, - startedTimeStamp: Date.now(), - refetch: action.payload.refetch, - }; - case "fetch": - return { - ...state, - isLoading: false, - isSuccess: false, - isError: false, - isFetching: true, - isUninitialized: false, - startedTimeStamp: Date.now(), - refetch: action.payload.refetch, - }; - case "success": - return { - ...state, - isLoading: false, - isFetching: false, - isError: false, - isUninitialized: false, - isSuccess: true, - data: action.payload.data, - currentData: action.payload.data, - fulfilledTimeStamp: Date.now(), - }; - case "error": - return { - ...state, - isLoading: false, - isSuccess: false, - isFetching: false, - isUninitialized: false, - isError: true, - error: action.payload.error, - fulfilledTimeStamp: Date.now(), - }; - default: - return state; - } - }, - { - isLoading: true, - isSuccess: false, - isError: false, - isFetching: false, - refetch: () => {}, - isUninitialized: true, - currentData: undefined, - data: undefined, - error: undefined, - endpointName: "", - fulfilledTimeStamp: 0, - originalArgs: safeDependencies, - requestId, - startedTimeStamp: 0, - } - ); + const [state, dispatch] = R.useReducer(reducer, { + isLoading: true, + isSuccess: false, + isError: false, + isFetching: false, + refetch: () => {}, + isUninitialized: true, + currentData: undefined, + data: undefined, + error: undefined, + endpointName: "", + fulfilledTimeStamp: 0, + originalArgs: safeDependencies, + requestId, + startedTimeStamp: 0, + }); const runQuery = (overrideInitialized?: boolean) => { const fetchData = async () => { @@ -123,10 +67,65 @@ export const useCreateQuery = ( R.useEffect(() => runQuery(), safeDependencies); - return state; + return state as Types.UseQueryResult; }; export const _testCreateUseCreateQuery = (react: any) => { R = react as ReactType; return useCreateQuery; }; + +const reducer = ( + state: Types.UseQueryResult, + action: Types.CreateQueryReducerAction +) => { + switch (action.type) { + case "load": + return { + ...state, + isSuccess: false, + isError: false, + isFetching: false, + isLoading: true, + isUninitialized: false, + startedTimeStamp: Date.now(), + refetch: action.payload.refetch, + }; + case "fetch": + return { + ...state, + isLoading: false, + isSuccess: false, + isError: false, + isFetching: true, + isUninitialized: false, + startedTimeStamp: Date.now(), + refetch: action.payload.refetch, + }; + case "success": + return { + ...state, + isLoading: false, + isFetching: false, + isError: false, + isUninitialized: false, + isSuccess: true, + data: action.payload.data, + currentData: action.payload.data, + fulfilledTimeStamp: Date.now(), + }; + case "error": + return { + ...state, + isLoading: false, + isSuccess: false, + isFetching: false, + isUninitialized: false, + isError: true, + error: action.payload.error, + fulfilledTimeStamp: Date.now(), + }; + default: + return state; + } +}; diff --git a/src/index.ts b/src/index.ts index 4a5ece9..af7476c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,31 +1,31 @@ +export { AwaitLoader } from "./AwaitLoader"; +export { RTKLoader } from "./RTKLoader"; export { aggregateToQuery } from "./aggregateToQuery"; export { createLoader, createUseLoader } from "./createLoader"; export { useCreateQuery } from "./createQuery"; -export { RTKLoader } from "./RTKLoader"; export type { Component, ComponentWithLoaderData, ConsumerProps, - CreateUseLoaderArgs, CreateLoaderArgs, - DeferredConfig, - LoaderConfig, - _TDeferred, - _TPayload, - _TQueries, - _TProps, - _TReturn, - MakeDataRequired, + CreateUseLoaderArgs, CustomLoaderProps, DataShapeInput, + DeferredConfig, InferLoaderData, Loader, + LoaderConfig, LoaderTransformFunction, + MakeDataRequired, OptionalGenericArg, UseLoader, UseQueryResult, WithLoaderArgs, + _TDeferred, + _TPayload, + _TProps, + _TQueries, + _TReturn, } from "./types"; -export { withLoader } from "./withLoader"; -export { AwaitLoader } from "./AwaitLoader"; export { useCreateLoader } from "./useCreateLoader"; +export { withLoader } from "./withLoader"; diff --git a/testing-app/src/components/ErrorBoundary.tsx b/testing-app/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..6511d7f --- /dev/null +++ b/testing-app/src/components/ErrorBoundary.tsx @@ -0,0 +1,38 @@ +import React from "react"; + +export class ErrorBoundary extends React.Component< + { + children?: React.ReactNode; + fallback?: React.ReactNode; + }, + { + hasError: boolean; + } +> { + public state = { + hasError: false, + }; + + public static getDerivedStateFromError(_: Error) { + return { hasError: true }; + } + + public componentDidCatch( + error: Error, + errorInfo: React.ErrorInfo + ) { + console.error("Uncaught error:", error, errorInfo); + } + + public render() { + if (this.state.hasError) { + return ( +

{this.props.fallback ?? "_error_boundary_"}

+ ); + } + + return this.props.children; + } +} + +export default ErrorBoundary; diff --git a/testing-app/src/tests.test.tsx b/testing-app/src/tests.test.tsx index 08900a1..4b386c9 100644 --- a/testing-app/src/tests.test.tsx +++ b/testing-app/src/tests.test.tsx @@ -5,6 +5,7 @@ import { createLoader } from "../../src/createLoader"; import { _testCreateUseCreateQuery } from "../../src/createQuery"; import { CustomLoaderProps } from "../../src/types"; import { withLoader } from "../../src/withLoader"; +import ErrorBoundary from "./components/ErrorBoundary"; import { useGetPokemonByNameQuery, useGetPokemonsQuery, @@ -872,7 +873,7 @@ describe("createLoader", () => { ); }); - test.skip("Can partially extend config", async () => { + test("Can partially extend config", async () => { const CustomLoader = (props: CustomLoaderProps) => { if (props.query.isError) { return
Custom error!
; @@ -919,40 +920,3 @@ describe("createLoader", () => { }); }); }); - -class ErrorBoundary extends React.Component< - { - children?: React.ReactNode; - fallback?: React.ReactNode; - }, - { - hasError: boolean; - } -> { - public state = { - hasError: false, - }; - - public static getDerivedStateFromError(_: Error) { - return { hasError: true }; - } - - public componentDidCatch( - error: Error, - errorInfo: React.ErrorInfo - ) { - console.error("Uncaught error:", error, errorInfo); - } - - public render() { - if (this.state.hasError) { - return ( -

{this.props.fallback ?? "_error_boundary_"}

- ); - } - - return this.props.children; - } -} - -export default ErrorBoundary;