From b91517afd55b91a62dffc7e4a79e1c7e76e4504c Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 23 Nov 2024 20:20:36 -0800 Subject: [PATCH] Add React Query (cherry picked from commit 4491df3ae7530f2167beebc3548dd01fd2cc1a12) --- frontend/src/App/App.tsx | 21 +++++---- frontend/src/Helpers/Hooks/useApiQuery.ts | 56 +++++++++++++++++++++++ frontend/typings/Globals.d.ts | 1 + package.json | 1 + yarn.lock | 12 +++++ 5 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 frontend/src/Helpers/Hooks/useApiQuery.ts diff --git a/frontend/src/App/App.tsx b/frontend/src/App/App.tsx index 166bf5dec5..c3443eb6ea 100644 --- a/frontend/src/App/App.tsx +++ b/frontend/src/App/App.tsx @@ -1,3 +1,4 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ConnectedRouter, ConnectedRouterProps } from 'connected-react-router'; import React from 'react'; import DocumentTitle from 'react-document-title'; @@ -12,17 +13,21 @@ interface AppProps { history: ConnectedRouterProps['history']; } +const queryClient = new QueryClient(); + function App({ store, history }: AppProps) { return ( - - - - - - - - + + + + + + + + + + ); } diff --git a/frontend/src/Helpers/Hooks/useApiQuery.ts b/frontend/src/Helpers/Hooks/useApiQuery.ts new file mode 100644 index 0000000000..5120e42212 --- /dev/null +++ b/frontend/src/Helpers/Hooks/useApiQuery.ts @@ -0,0 +1,56 @@ +import { useQuery } from '@tanstack/react-query'; +import { useMemo } from 'react'; + +interface QueryOptions { + url: string; + headers?: HeadersInit; +} + +const absUrlRegex = /^(https?:)?\/\//i; +const apiRoot = window.Radarr.apiRoot; + +function isAbsolute(url: string) { + return absUrlRegex.test(url); +} + +function getUrl(url: string) { + return apiRoot + url; +} + +function useApiQuery(options: QueryOptions) { + const { url, headers } = options; + + const final = useMemo(() => { + if (isAbsolute(url)) { + return { + url, + headers, + }; + } + + return { + url: getUrl(url), + headers: { + ...headers, + 'X-Api-Key': window.Radarr.apiKey, + }, + }; + }, [url, headers]); + + return useQuery({ + queryKey: [final.url], + queryFn: async () => { + const result = await fetch(final.url, { + headers: final.headers, + }); + + if (!result.ok) { + throw new Error('Failed to fetch'); + } + + return result.json() as T; + }, + }); +} + +export default useApiQuery; diff --git a/frontend/typings/Globals.d.ts b/frontend/typings/Globals.d.ts index 21e40447bd..51ba66e950 100644 --- a/frontend/typings/Globals.d.ts +++ b/frontend/typings/Globals.d.ts @@ -3,6 +3,7 @@ declare module '*.module.css'; interface Window { Radarr: { apiKey: string; + apiRoot: string; instanceName: string; theme: string; urlBase: string; diff --git a/package.json b/package.json index 2ab9c29268..9b410fe0c6 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@microsoft/signalr": "6.0.25", "@sentry/browser": "7.119.1", "@sentry/integrations": "7.119.1", + "@tanstack/react-query": "5.74.3", "@types/node": "20.16.11", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", diff --git a/yarn.lock b/yarn.lock index 9e304e216e..3865736aea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1295,6 +1295,18 @@ dependencies: "@sentry/types" "7.119.1" +"@tanstack/query-core@5.74.3": + version "5.74.3" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.74.3.tgz#1fc97bd9a47f2acdf9f49737b1e6969e7bbcb7d7" + integrity sha512-Mqk+5o3qTuAiZML248XpNH8r2cOzl15+LTbUsZQEwvSvn1GU4VQhvqzAbil36p+MBxpr/58oBSnRzhrBevDhfg== + +"@tanstack/react-query@5.74.3": + version "5.74.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.74.3.tgz#f7acd825abaea091f009d1c3f115212e45c4ee74" + integrity sha512-QrycUn0wxjVPzITvQvOxFRdhlAwIoOQSuav7qWD4SWCoKCdLbyRZ2vji2GuBq/glaxbF4wBx3fqcYRDOt8KDTA== + dependencies: + "@tanstack/query-core" "5.74.3" + "@types/archiver@^5.3.1": version "5.3.4" resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-5.3.4.tgz#32172d5a56f165b5b4ac902e366248bf03d3ae84"