// app/router/index.tsx import createBrowserRouter from 'react-router-dom'; import lazy, Suspense from 'react'; const DashboardPage = lazy(() => import('@/features/dashboard/pages/DashboardPage')); const ProductsPage = lazy(() => import('@/features/products/pages/ProductsPage')); const NotFoundPage = lazy(() => import('@/shared/ui/NotFoundPage'));

apiClient.interceptors.request.use((config) => const token = localStorage.getItem('accessToken'); if (token) config.headers.Authorization = Bearer $token ; return config; );

| State Type | Solution | Example | |------------|----------|---------| | | TanStack Query (React Query) + fetch | List of users, product details | | URL state | React Router | Query params, route params | | Client global state | Zustand / Redux Toolkit | User session, theme preference | | Local UI state | useState / useReducer | Form input, modal open/close |

export const useAuthStore = create<AuthStore>((set) => ( user: null, isAuthenticated: false, login: (user) => set( user, isAuthenticated: true ), logout: () => set( user: null, isAuthenticated: false ), )); Never call fetch or axios directly inside a component. Build a structured data layer:

); // features/products/hooks/useProducts.ts import useQuery from '@tanstack/react-query'; import apiClient from '@/shared/api/client'; export const useProducts = () => return useQuery( queryKey: ['products'], queryFn: () => apiClient.get('/products').then(res => res.data), staleTime: 5 * 60 * 1000, // 5 minutes ); ; 6. Routing and Code Splitting Use lazy loading at the route level to split your bundle: