feat: introduce react-query and react-query-devtools

This commit is contained in:
Ali BARIN
2024-02-29 17:34:18 +00:00
parent 487c621fa5
commit 83815d3caa
8 changed files with 240 additions and 14 deletions

View File

@@ -0,0 +1,55 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import api from 'helpers/api.js';
import useAuthentication from 'hooks/useAuthentication.js';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
// provides a convenient default while it should be overridden for other HTTP methods
queryFn: async ({ queryKey, signal }) => {
const { data } = await api.get(queryKey[0], {
signal,
});
return data;
},
retry: false,
},
},
});
export default function AutomatischQueryClientProvider({ children }) {
const { token, initialize } = useAuthentication();
React.useEffect(
function updateTokenInHttpClient() {
if (!initialize) return;
if (token) {
api.defaults.headers.Authorization = token;
initialize();
} else {
delete api.defaults.headers.Authorization;
}
},
[initialize, token],
);
return (
<QueryClientProvider client={queryClient}>
{children}
<ReactQueryDevtools />
</QueryClientProvider>
);
}
AutomatischQueryClientProvider.propTypes = {
children: PropTypes.node.isRequired,
};

View File

@@ -1,6 +1,7 @@
const config = {
baseUrl: process.env.REACT_APP_BASE_URL,
graphqlUrl: process.env.REACT_APP_GRAPHQL_URL,
restApiUrl: process.env.REACT_APP_REST_API_URL,
chatwootBaseUrl: 'https://app.chatwoot.com',
supportEmailAddress: 'support@automatisch.io',
};

View File

@@ -0,0 +1,34 @@
import axios from 'axios';
import appConfig from 'config/app.js';
import * as URLS from 'config/urls.js';
import { getItem, removeItem } from 'helpers/storage.js';
const api = axios.create({
...axios.defaults,
baseURL: appConfig.restApiUrl,
headers: {
Authorization: getItem('token'),
},
});
api.interceptors.response.use(
(response) => response,
(error) => {
const status = error.response?.status;
if (status === 401) {
removeItem('token');
// hard reload to clear all state
if (window.location.pathname !== URLS.LOGIN) {
window.location.href = URLS.LOGIN;
}
}
// re-throw what's already intercepted here.
throw error;
},
);
export default api;

View File

@@ -1,8 +1,14 @@
const NAMESPACE = 'automatisch';
const makeKey = (key) => `${NAMESPACE}.${key}`;
export const setItem = (key, value) => {
return localStorage.setItem(makeKey(key), value);
};
export const getItem = (key) => {
return localStorage.getItem(makeKey(key));
};
export const removeItem = (key) => {
return localStorage.removeItem(makeKey(key));
};

View File

@@ -6,6 +6,7 @@ import SnackbarProvider from 'components/SnackbarProvider';
import MetadataProvider from 'components/MetadataProvider';
import { AuthenticationProvider } from 'contexts/Authentication';
import { AutomatischInfoProvider } from 'contexts/AutomatischInfo';
import QueryClientProvider from 'components/QueryClientProvider';
import Router from 'components/Router';
import LiveChat from 'components/LiveChat/index.ee';
import routes from 'routes';
@@ -18,19 +19,21 @@ root.render(
<Router>
<SnackbarProvider>
<AuthenticationProvider>
<ApolloProvider>
<AutomatischInfoProvider>
<IntlProvider>
<ThemeProvider>
<MetadataProvider>
{routes}
<QueryClientProvider>
<ApolloProvider>
<AutomatischInfoProvider>
<IntlProvider>
<ThemeProvider>
<MetadataProvider>
{routes}
<LiveChat />
</MetadataProvider>
</ThemeProvider>
</IntlProvider>
</AutomatischInfoProvider>
</ApolloProvider>
<LiveChat />
</MetadataProvider>
</ThemeProvider>
</IntlProvider>
</AutomatischInfoProvider>
</ApolloProvider>
</QueryClientProvider>
</AuthenticationProvider>
</SnackbarProvider>
</Router>,