main.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { StrictMode } from 'react'
  2. import ReactDOM from 'react-dom/client'
  3. import { AxiosError } from 'axios'
  4. import {
  5. QueryCache,
  6. QueryClient,
  7. QueryClientProvider,
  8. } from '@tanstack/react-query'
  9. import { RouterProvider, createRouter } from '@tanstack/react-router'
  10. import { toast } from 'sonner'
  11. import { useAuthStore } from '@/stores/auth-store'
  12. import { handleServerError } from '@/lib/handle-server-error'
  13. import { DirectionProvider } from './context/direction-provider'
  14. import { FontProvider } from './context/font-provider'
  15. import { ThemeProvider } from './context/theme-provider'
  16. // Generated Routes
  17. import { routeTree } from './routeTree.gen'
  18. // Styles
  19. import './styles/index.css'
  20. const queryClient = new QueryClient({
  21. defaultOptions: {
  22. queries: {
  23. retry: (failureCount, error) => {
  24. // eslint-disable-next-line no-console
  25. if (import.meta.env.DEV) console.log({ failureCount, error })
  26. if (failureCount >= 0 && import.meta.env.DEV) return false
  27. if (failureCount > 3 && import.meta.env.PROD) return false
  28. return !(
  29. error instanceof AxiosError &&
  30. [401, 403].includes(error.response?.status ?? 0)
  31. )
  32. },
  33. refetchOnWindowFocus: import.meta.env.PROD,
  34. staleTime: 10 * 1000, // 10s
  35. },
  36. mutations: {
  37. onError: (error) => {
  38. handleServerError(error)
  39. if (error instanceof AxiosError) {
  40. if (error.response?.status === 304) {
  41. toast.error('Content not modified!')
  42. }
  43. }
  44. },
  45. },
  46. },
  47. queryCache: new QueryCache({
  48. onError: (error) => {
  49. if (error instanceof AxiosError) {
  50. if (error.response?.status === 401) {
  51. toast.error('Session expired!')
  52. useAuthStore.getState().logout()
  53. const redirect = `${router.history.location.href}`
  54. router.navigate({ to: '/sign-in', search: { redirect } })
  55. }
  56. if (error.response?.status === 500) {
  57. toast.error('Internal Server Error!')
  58. // Only navigate to error page in production to avoid disrupting HMR in development
  59. if (import.meta.env.PROD) {
  60. router.navigate({ to: '/500' })
  61. }
  62. }
  63. if (error.response?.status === 403) {
  64. // router.navigate("/forbidden", { replace: true });
  65. }
  66. }
  67. },
  68. }),
  69. })
  70. // Create a new router instance
  71. const router = createRouter({
  72. routeTree,
  73. context: { queryClient },
  74. defaultPreload: 'intent',
  75. defaultPreloadStaleTime: 0,
  76. })
  77. // Register the router instance for type safety
  78. declare module '@tanstack/react-router' {
  79. interface Register {
  80. router: typeof router
  81. }
  82. }
  83. // Render the app
  84. const rootElement = document.getElementById('root')!
  85. if (!rootElement.innerHTML) {
  86. const root = ReactDOM.createRoot(rootElement)
  87. root.render(
  88. <StrictMode>
  89. <QueryClientProvider client={queryClient}>
  90. <ThemeProvider>
  91. <FontProvider>
  92. <DirectionProvider>
  93. <RouterProvider router={router} />
  94. </DirectionProvider>
  95. </FontProvider>
  96. </ThemeProvider>
  97. </QueryClientProvider>
  98. </StrictMode>
  99. )
  100. }