From 8eec8f3a09313db7ebd45e228ac3791f0d0b4a1d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 9 Aug 2022 10:24:43 -0500 Subject: [PATCH] react-query: use legacy API client with hooks --- app/soapbox/containers/soapbox.tsx | 16 +++++-------- app/soapbox/hooks/index.ts | 1 + app/soapbox/hooks/useApi.ts | 12 ++++++++++ app/soapbox/jest/test-helpers.tsx | 4 +--- app/soapbox/queries/carousels.ts | 14 +++++++----- app/soapbox/queries/client.ts | 36 +----------------------------- 6 files changed, 28 insertions(+), 55 deletions(-) create mode 100644 app/soapbox/hooks/useApi.ts diff --git a/app/soapbox/containers/soapbox.tsx b/app/soapbox/containers/soapbox.tsx index 1a87ec4e8..413673775 100644 --- a/app/soapbox/containers/soapbox.tsx +++ b/app/soapbox/containers/soapbox.tsx @@ -13,7 +13,6 @@ import { loadInstance } from 'soapbox/actions/instance'; import { fetchMe } from 'soapbox/actions/me'; import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox'; import { fetchVerificationConfig } from 'soapbox/actions/verification'; -import { getAuthBaseURL } from 'soapbox/api'; import * as BuildConfig from 'soapbox/build_config'; import GdprBanner from 'soapbox/components/gdpr-banner'; import Helmet from 'soapbox/components/helmet'; @@ -39,8 +38,7 @@ import { useLocale, } from 'soapbox/hooks'; import MESSAGES from 'soapbox/locales/messages'; -import { queryClient, useAxiosInterceptors } from 'soapbox/queries/client'; -import { getAccessToken } from 'soapbox/utils/auth'; +import { queryClient } from 'soapbox/queries/client'; import { useCachedLocationHandler } from 'soapbox/utils/redirect'; import { generateThemeCss } from 'soapbox/utils/theme'; @@ -202,12 +200,8 @@ const SoapboxLoad: React.FC = ({ children }) => { const me = useAppSelector(state => state.me); const account = useOwnAccount(); const swUpdating = useAppSelector(state => state.meta.swUpdating); - const accessToken = useAppSelector((state) => getAccessToken(state)); - const baseURL = useAppSelector((state) => me ? getAuthBaseURL(state, me) : ''); const locale = useLocale(); - useAxiosInterceptors(accessToken, baseURL); - const [messages, setMessages] = useState>({}); const [localeLoading, setLocaleLoading] = useState(true); const [isLoaded, setIsLoaded] = useState(false); @@ -289,15 +283,15 @@ const SoapboxHead: React.FC = ({ children }) => { /** The root React node of the application. */ const Soapbox: React.FC = () => { return ( - - + + - - + + ); }; diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index aad62b1f1..4d7417771 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -1,4 +1,5 @@ export { useAccount } from './useAccount'; +export { useApi } from './useApi'; export { useAppDispatch } from './useAppDispatch'; export { useAppSelector } from './useAppSelector'; export { useDimensions } from './useDimensions'; diff --git a/app/soapbox/hooks/useApi.ts b/app/soapbox/hooks/useApi.ts new file mode 100644 index 000000000..1d98a6166 --- /dev/null +++ b/app/soapbox/hooks/useApi.ts @@ -0,0 +1,12 @@ +import api from 'soapbox/api'; + +import { useAppDispatch } from './useAppDispatch'; + +/** Use stateful Axios client with auth from Redux. */ +export const useApi = () => { + const dispatch = useAppDispatch(); + + return dispatch((_dispatch, getState) => { + return api(getState); + }); +}; diff --git a/app/soapbox/jest/test-helpers.tsx b/app/soapbox/jest/test-helpers.tsx index f48bf09f3..e0761eb27 100644 --- a/app/soapbox/jest/test-helpers.tsx +++ b/app/soapbox/jest/test-helpers.tsx @@ -11,8 +11,6 @@ import { Action, applyMiddleware, createStore } from 'redux'; import thunk from 'redux-thunk'; import '@testing-library/jest-dom'; -import API from 'soapbox/queries/client'; - import NotificationsContainer from '../features/ui/containers/notifications_container'; import { default as rootReducer } from '../reducers'; @@ -29,7 +27,7 @@ const applyActions = (state: any, actions: any, reducer: any) => { return actions.reduce((state: any, action: any) => reducer(state, action), state); }; -const mock = new MockAdapter(API, { onNoMatch: 'throwException' }); +const mock = new MockAdapter(undefined as any, { onNoMatch: 'throwException' }); const queryClient = new QueryClient({ logger: { // eslint-disable-next-line no-console diff --git a/app/soapbox/queries/carousels.ts b/app/soapbox/queries/carousels.ts index 2989f4a52..7d295183e 100644 --- a/app/soapbox/queries/carousels.ts +++ b/app/soapbox/queries/carousels.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query'; -import API from 'soapbox/queries/client'; +import { useApi } from 'soapbox/hooks'; type Avatar = { account_id: string @@ -8,12 +8,14 @@ type Avatar = { username: string } -const getCarouselAvatars = async() => { - const { data } = await API.get('/api/v1/truth/carousels/avatars'); - return data; -}; - export default function useCarouselAvatars() { + const api = useApi(); + + const getCarouselAvatars = async() => { + const { data } = await api.get('/api/v1/truth/carousels/avatars'); + return data; + }; + const result = useQuery(['carouselAvatars'], getCarouselAvatars, { placeholderData: [], }); diff --git a/app/soapbox/queries/client.ts b/app/soapbox/queries/client.ts index beddfa773..d772e9288 100644 --- a/app/soapbox/queries/client.ts +++ b/app/soapbox/queries/client.ts @@ -1,20 +1,4 @@ import { QueryClient } from '@tanstack/react-query'; -import axios, { AxiosRequestConfig } from 'axios'; - -import * as BuildConfig from 'soapbox/build_config'; -import { isURL } from 'soapbox/utils/auth'; - -const maybeParseJSON = (data: string) => { - try { - return JSON.parse(data); - } catch (Exception) { - return data; - } -}; - -const API = axios.create({ - transformResponse: [maybeParseJSON], -}); const queryClient = new QueryClient({ defaultOptions: { @@ -26,22 +10,4 @@ const queryClient = new QueryClient({ }, }); -const useAxiosInterceptors = (token: string, baseApiUri: string) => { - API.interceptors.request.use( - async(config: AxiosRequestConfig) => { - if (token) { - config.baseURL = isURL(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : baseApiUri; - // eslint-disable-next-line no-param-reassign - config.headers = { - ...config.headers, - Authorization: (token ? `Bearer ${token}` : null) as string | number | boolean | string[] | undefined, - } as any; - } - - return config; - }, - (error) => Promise.reject(error), - ); -}; - -export { API as default, queryClient, useAxiosInterceptors }; +export { queryClient };