react-query: use legacy API client with hooks

This commit is contained in:
Alex Gleason 2022-08-09 10:24:43 -05:00
parent 6b297c3a7e
commit 8eec8f3a09
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
6 changed files with 28 additions and 55 deletions

View File

@ -13,7 +13,6 @@ import { loadInstance } from 'soapbox/actions/instance';
import { fetchMe } from 'soapbox/actions/me'; import { fetchMe } from 'soapbox/actions/me';
import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox'; import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox';
import { fetchVerificationConfig } from 'soapbox/actions/verification'; import { fetchVerificationConfig } from 'soapbox/actions/verification';
import { getAuthBaseURL } from 'soapbox/api';
import * as BuildConfig from 'soapbox/build_config'; import * as BuildConfig from 'soapbox/build_config';
import GdprBanner from 'soapbox/components/gdpr-banner'; import GdprBanner from 'soapbox/components/gdpr-banner';
import Helmet from 'soapbox/components/helmet'; import Helmet from 'soapbox/components/helmet';
@ -39,8 +38,7 @@ import {
useLocale, useLocale,
} from 'soapbox/hooks'; } from 'soapbox/hooks';
import MESSAGES from 'soapbox/locales/messages'; import MESSAGES from 'soapbox/locales/messages';
import { queryClient, useAxiosInterceptors } from 'soapbox/queries/client'; import { queryClient } from 'soapbox/queries/client';
import { getAccessToken } from 'soapbox/utils/auth';
import { useCachedLocationHandler } from 'soapbox/utils/redirect'; import { useCachedLocationHandler } from 'soapbox/utils/redirect';
import { generateThemeCss } from 'soapbox/utils/theme'; import { generateThemeCss } from 'soapbox/utils/theme';
@ -202,12 +200,8 @@ const SoapboxLoad: React.FC<ISoapboxLoad> = ({ children }) => {
const me = useAppSelector(state => state.me); const me = useAppSelector(state => state.me);
const account = useOwnAccount(); const account = useOwnAccount();
const swUpdating = useAppSelector(state => state.meta.swUpdating); const swUpdating = useAppSelector(state => state.meta.swUpdating);
const accessToken = useAppSelector((state) => getAccessToken(state));
const baseURL = useAppSelector((state) => me ? getAuthBaseURL(state, me) : '');
const locale = useLocale(); const locale = useLocale();
useAxiosInterceptors(accessToken, baseURL);
const [messages, setMessages] = useState<Record<string, string>>({}); const [messages, setMessages] = useState<Record<string, string>>({});
const [localeLoading, setLocaleLoading] = useState(true); const [localeLoading, setLocaleLoading] = useState(true);
const [isLoaded, setIsLoaded] = useState(false); const [isLoaded, setIsLoaded] = useState(false);
@ -289,15 +283,15 @@ const SoapboxHead: React.FC<ISoapboxHead> = ({ children }) => {
/** The root React node of the application. */ /** The root React node of the application. */
const Soapbox: React.FC = () => { const Soapbox: React.FC = () => {
return ( return (
<QueryClientProvider client={queryClient}>
<Provider store={store}> <Provider store={store}>
<QueryClientProvider client={queryClient}>
<SoapboxHead> <SoapboxHead>
<SoapboxLoad> <SoapboxLoad>
<SoapboxMount /> <SoapboxMount />
</SoapboxLoad> </SoapboxLoad>
</SoapboxHead> </SoapboxHead>
</Provider>
</QueryClientProvider> </QueryClientProvider>
</Provider>
); );
}; };

View File

@ -1,4 +1,5 @@
export { useAccount } from './useAccount'; export { useAccount } from './useAccount';
export { useApi } from './useApi';
export { useAppDispatch } from './useAppDispatch'; export { useAppDispatch } from './useAppDispatch';
export { useAppSelector } from './useAppSelector'; export { useAppSelector } from './useAppSelector';
export { useDimensions } from './useDimensions'; export { useDimensions } from './useDimensions';

View File

@ -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);
});
};

View File

@ -11,8 +11,6 @@ import { Action, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk'; import thunk from 'redux-thunk';
import '@testing-library/jest-dom'; import '@testing-library/jest-dom';
import API from 'soapbox/queries/client';
import NotificationsContainer from '../features/ui/containers/notifications_container'; import NotificationsContainer from '../features/ui/containers/notifications_container';
import { default as rootReducer } from '../reducers'; 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); 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({ const queryClient = new QueryClient({
logger: { logger: {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console

View File

@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import API from 'soapbox/queries/client'; import { useApi } from 'soapbox/hooks';
type Avatar = { type Avatar = {
account_id: string account_id: string
@ -8,12 +8,14 @@ type Avatar = {
username: string username: string
} }
export default function useCarouselAvatars() {
const api = useApi();
const getCarouselAvatars = async() => { const getCarouselAvatars = async() => {
const { data } = await API.get('/api/v1/truth/carousels/avatars'); const { data } = await api.get('/api/v1/truth/carousels/avatars');
return data; return data;
}; };
export default function useCarouselAvatars() {
const result = useQuery<Avatar[]>(['carouselAvatars'], getCarouselAvatars, { const result = useQuery<Avatar[]>(['carouselAvatars'], getCarouselAvatars, {
placeholderData: [], placeholderData: [],
}); });

View File

@ -1,20 +1,4 @@
import { QueryClient } from '@tanstack/react-query'; 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({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
@ -26,22 +10,4 @@ const queryClient = new QueryClient({
}, },
}); });
const useAxiosInterceptors = (token: string, baseApiUri: string) => { export { queryClient };
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 };