Skip to content

Troubleshooting Guide

This comprehensive troubleshooting guide helps you quickly identify and resolve common issues when working with the React Admin Template. Each section provides practical solutions based on real-world scenarios.

Problem: Build failures or dependency installation errors due to Node.js version mismatch.

Solution:

  1. Check your current Node.js version:

    Terminal window
    node --version
  2. If your version is below 20.19.0, update Node.js using nvm or fnm:

    Using nvm:

    Terminal window
    nvm install 20.19.0
    nvm use 20.19.0
    nvm alias default 20.19.0

    Using fnm:

    Terminal window
    fnm install 20.19.0
    fnm use 20.19.0
    fnm default 20.19.0
  3. Clear package manager cache and reinstall dependencies:

    Terminal window
    rm -rf node_modules package-lock.json
    npm cache clean --force
    npm install

Problem: Dependency conflicts when using different package managers (npm, pnpm, yarn).

Solution: The template is optimized for pnpm. Always use pnpm for consistency:

Terminal window
# Install pnpm globally
npm install -g pnpm
# Install dependencies
pnpm install
# Run development server
pnpm dev

Problem: Import statements using @/ alias fail with module resolution errors.

Symptom:

Cannot find module '@/components/ui/button' or its corresponding type declarations.

Solution: Ensure your tsconfig.json includes the correct path mapping:

tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src", "globals.d.ts"]
}

Problem: TypeScript strict mode flags unused variables or parameters.

Symptom:

'React' is declared but its value is never read.
Parameter 'event' is declared but its value is never used.

Solutions:

// ❌ Incorrect - React not needed in React 19
import React from 'react'
// ✅ Correct - Only import what you use
import { useState, useEffect } from 'react'

Problem: TypeScript errors for imported assets (CSS, SVG, etc.).

Solution: Ensure globals.d.ts includes all necessary module declarations:

globals.d.ts
declare module '*.css'
declare module '*.vue'
declare module '*.json'
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'

Problem: Development server fails to start or shows CORS errors.

Solutions:

Port Conflicts

Terminal window
# Check what's running on port 9000
lsof -ti:9000
# Kill process if needed
kill -9 $(lsof -ti:9000)
# Start with different port
pnpm dev --port 3000

Network Access

vite.config.ts
export default defineConfig({
server: {
port: 9000,
host: '0.0.0.0', // Allow external access
strictPort: true,
},
})

Problem: Large bundle size or slow build times.

Diagnostic Steps:

  1. Analyze bundle size:

    Terminal window
    pnpm build
    pnpm preview
  2. Check for large dependencies by installing bundle analyzer:

    Terminal window
    pnpm add -D rollup-plugin-visualizer

    Then add to vite.config.ts plugins array:

    import { visualizer } from 'rollup-plugin-visualizer'
    plugins: [
    // ... other plugins
    visualizer({ filename: 'dist/stats.html', open: true })
    ]
  3. Optimize imports to reduce bundle size:

    // ❌ Imports entire library
    import { format, parseISO, addDays } from 'date-fns'
    // ✅ Tree-shaking friendly
    import format from 'date-fns/format'
    import parseISO from 'date-fns/parseISO'
    import addDays from 'date-fns/addDays'

Problem: Table becomes slow with large datasets or frequent re-renders.

Solutions:

// ✅ Memoize expensive calculations
const processedData = useMemo(() => {
return rawData.map(item => ({
...item,
calculatedValue: expensiveCalculation(item)
}))
}, [rawData])
// ✅ Use useCallback for stable references
const handleRowClick = useCallback((row) => {
console.log('Row clicked:', row.id)
}, [])
// ✅ Implement virtual scrolling for large datasets
const tableConfig = {
enableVirtualization: true,
estimateSize: () => 35, // Row height in pixels
overscan: 10
}

Problem: Form validation errors or performance issues with large forms.

Solutions:

// ✅ Use schema-level validation instead of field-level
const formSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
}).refine((data) => {
// Complex cross-field validation here
return data.password !== data.email
}, {
message: "Password cannot be the same as email",
path: ["password"],
})

Problem: OKLCH color values not working or theme switching failures.

Diagnostic:

// Check if CSS custom properties are properly set
const rootStyles = getComputedStyle(document.documentElement)
console.log('Primary color:', rootStyles.getPropertyValue('--primary'))
// Verify OKLCH browser support
const supportsOKLCH = CSS.supports('color', 'oklch(70% 0.25 180)')
console.log('OKLCH supported:', supportsOKLCH)

Solution: Add fallback for older browsers:

// In your CSS
:root {
--primary: oklch(58.5% 0.233 277.117);
--primary-fallback: #4f46e5; /* Fallback for older browsers */
}
// Use with fallback
.primary-button {
background-color: var(--primary-fallback);
background-color: var(--primary);
}

Problem: State not persisting between browser sessions or hydration mismatches.

Solutions:

// ✅ Handle hydration properly
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
export const useStore = create(
persist(
(set, get) => ({
// Your state here
}),
{
name: 'app-storage',
storage: createJSONStorage(() => localStorage),
// Handle hydration
onRehydrateStorage: (state) => {
console.log('Hydration started')
return (state, error) => {
if (error) {
console.log('Hydration error:', error)
} else {
console.log('Hydration finished')
}
}
},
}
)
)

Problem: State not updating across components or hook dependencies causing infinite loops.

Solution:

// ✅ Use proper dependency arrays
const { theme, setTheme } = useThemeStore()
const [localTheme, setLocalTheme] = useState(theme)
useEffect(() => {
setLocalTheme(theme)
}, [theme]) // Only depend on theme
// ✅ Avoid object dependencies
const config = useMemo(() => ({
theme: theme,
colors: colors
}), [theme, colors]) // List dependencies explicitly

Problem: Code works locally but fails in production build.

Common Causes & Solutions:

Environment Variables

Terminal window
# ❌ Missing VITE_ prefix
REACT_APP_API_URL=https://api.example.com
# ✅ Correct Vite environment variable
VITE_API_URL=https://api.example.com

Dynamic Imports

// ✅ Handle dynamic import errors
const LazyComponent = lazy(() =>
import('./Component').catch(() => ({
default: () => <div>Failed to load component</div>
}))
)

Problem: Images or assets not loading in production.

Solution: Use proper asset imports and public folder structure:

// ✅ For assets in src/assets
import logo from '@/assets/images/logo.png'
// ✅ For assets in public folder
const logoUrl = '/images/logo.png'
// ✅ Dynamic imports with proper error handling
const loadImage = async (imageName: string) => {
try {
const image = await import(`@/assets/images/${imageName}.png`)
return image.default
} catch (error) {
console.warn('Image not found:', imageName)
return '/images/fallback.png'
}
}

Problem: Application slows down over time due to memory leaks.

Solutions:

// ✅ Clean up event listeners
useEffect(() => {
const handleResize = () => {
// Handle resize
}
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
// ✅ Cancel async operations
useEffect(() => {
let cancelled = false
const fetchData = async () => {
try {
const data = await api.getData()
if (!cancelled) {
setData(data)
}
} catch (error) {
if (!cancelled) {
setError(error)
}
}
}
fetchData()
return () => {
cancelled = true
}
}, [])

Problem: Large initial bundle affecting loading performance.

Solution: Implement code splitting and lazy loading:

// ✅ Route-level code splitting
const Dashboard = lazy(() => import('@/pages/Dashboard'))
const UserManagement = lazy(() => import('@/pages/UserManagement'))
// ✅ Component-level code splitting
const HeavyChart = lazy(() => import('@/components/Charts/HeavyChart'))
// ✅ Wrap in Suspense with proper fallback
<Suspense fallback={<ComponentLoader />}>
<HeavyChart data={chartData} />
</Suspense>

Essential debugging setup:

  1. Install React Developer Tools browser extension

  2. Enable Zustand devtools in your store:

    import { devtools } from 'zustand/middleware'
    export const useStore = create(
    devtools(
    persist(
    // Your store implementation
    ),
    { name: 'app-store' }
    )
    )
  3. Add error boundaries for better error handling:

    import { ErrorBoundary } from 'react-error-boundary'
    function ErrorFallback({ error, resetErrorBoundary }) {
    return (
    <div role="alert" className="p-4 border border-red-200 rounded-lg">
    <h2>Something went wrong:</h2>
    <pre>{error.message}</pre>
    <button onClick={resetErrorBoundary}>Try again</button>
    </div>
    )
    }
    // Wrap your app or components
    <ErrorBoundary
    FallbackComponent={ErrorFallback}
    onError={(error, errorInfo) => {
    console.error('Error caught by boundary:', error, errorInfo)
    }}
    >
    <YourComponent />
    </ErrorBoundary>

Useful debugging techniques:

// ✅ Debug state changes
useEffect(() => {
console.log('State changed:', { currentState, previousState })
}, [currentState])
// ✅ Debug re-renders
useEffect(() => {
console.log('Component re-rendered')
})
// ✅ Debug performance
const expensiveOperation = () => {
console.time('expensive-operation')
const result = heavyCalculation()
console.timeEnd('expensive-operation')
return result
}

When you encounter issues not covered in this guide:

Check Dependencies

Ensure all package versions are compatible and up-to-date. Check the template’s package.json for reference versions.

Review Error Logs

Always check both browser console and terminal output for complete error information and stack traces.

Minimal Reproduction

Create a minimal example that reproduces the issue to isolate the problem from other code.

Environment Reset

When in doubt, clear all caches, delete node_modules, and perform a fresh installation.