How to build a dashboard in React
Building a dashboard in React requires a layout with a sidebar and header, lazy-loaded routes for each section, and data visualization components that load data asynchronously.
As the creator of CoreUI — an open-source UI framework used by over 500,000 developers — I designed the React dashboard template architecture that powers thousands of production admin panels.
The key pattern is a layout wrapper component that renders the sidebar, header, and a content area with <Outlet />, combined with React Router’s lazy() for code splitting.
This ensures the initial bundle is small and each dashboard section loads only when visited.
Install CoreUI React and React Router.
npm install @coreui/react @coreui/icons-react react-router-dom
// layouts/DefaultLayout.jsx
import { Suspense } from 'react'
import { Outlet } from 'react-router-dom'
import {
CSidebar,
CSidebarBrand,
CSidebarNav,
CNavItem,
CNavTitle,
CContainer
} from '@coreui/react'
import CIcon from '@coreui/icons-react'
import { cilSpeedometer, cilPeople, cilChartLine, cilSettings } from '@coreui/icons'
const navItems = [
{ component: CNavTitle, name: 'Main' },
{ component: CNavItem, name: 'Dashboard', to: '/dashboard', icon: <CIcon icon={cilSpeedometer} /> },
{ component: CNavItem, name: 'Users', to: '/users', icon: <CIcon icon={cilPeople} /> },
{ component: CNavItem, name: 'Analytics', to: '/analytics', icon: <CIcon icon={cilChartLine} /> },
{ component: CNavItem, name: 'Settings', to: '/settings', icon: <CIcon icon={cilSettings} /> }
]
export function DefaultLayout() {
return (
<div>
<CSidebar colorScheme="dark" position="fixed">
<CSidebarBrand>My Dashboard</CSidebarBrand>
<CSidebarNav>
{navItems.map((item, i) => {
const { component: Comp, name, to, icon } = item
return to
? <CNavItem key={i} href={to}>{icon} {name}</CNavItem>
: <CNavTitle key={i}>{name}</CNavTitle>
})}
</CSidebarNav>
</CSidebar>
<div className="wrapper d-flex flex-column min-vh-100 ms-sidebar">
<div className="body flex-grow-1 p-3">
<CContainer lg>
<Suspense fallback={<div>Loading...</div>}>
<Outlet />
</Suspense>
</CContainer>
</div>
</div>
</div>
)
}
Lazy-Loaded Routes
Code-split each dashboard section.
// App.jsx
import { lazy } from 'react'
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { DefaultLayout } from './layouts/DefaultLayout'
import { ProtectedRoute } from './components/ProtectedRoute'
const Dashboard = lazy(() => import('./views/Dashboard'))
const Users = lazy(() => import('./views/Users'))
const Analytics = lazy(() => import('./views/Analytics'))
const Login = lazy(() => import('./views/Login'))
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute />}>
<Route element={<DefaultLayout />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/users" element={<Users />} />
<Route path="/analytics" element={<Analytics />} />
<Route path="/" element={<Navigate to="/dashboard" replace />} />
</Route>
</Route>
</Routes>
</BrowserRouter>
)
}
lazy() creates code-split chunks for each section. The Suspense in DefaultLayout shows “Loading…” while the chunk downloads. ProtectedRoute wraps all authenticated routes.
Stats Cards Component
Display KPIs with CoreUI cards.
// views/Dashboard.jsx
import { CCard, CCardBody, CRow, CCol, CProgress } from '@coreui/react'
const stats = [
{ label: 'Users', value: '9,828', progress: 75, color: 'info' },
{ label: 'Revenue', value: '$6,200', progress: 60, color: 'success' },
{ label: 'Orders', value: '2,371', progress: 43, color: 'warning' },
{ label: 'Growth', value: '18%', progress: 18, color: 'primary' }
]
export default function Dashboard() {
return (
<CRow>
{stats.map(stat => (
<CCol key={stat.label} sm={6} xl={3}>
<CCard className="mb-4">
<CCardBody>
<div className="fs-4 fw-semibold">{stat.value}</div>
<div className="text-muted">{stat.label}</div>
<CProgress className="mt-3" color={stat.color} value={stat.progress} />
</CCardBody>
</CCard>
</CCol>
))}
</CRow>
)
}
Best Practice Note
This is the exact architecture used in CoreUI React Admin Template, which provides a complete production-ready starting point with authentication, routing, charts, and a full CoreUI component library wired together. For teams building enterprise dashboards, starting from the CoreUI template saves significant setup time. See how to integrate React with REST API to connect your dashboard to real-time data.



