Master React Router v6 for production routing with error boundaries, lazy loading, and navigation guards
Implements React Router v6 for SPA navigation with nested routes, protected routes, and URL parameter handling. Use when building multi-page React apps requiring client-side routing, navigation guards, or dynamic route patterns.
/plugin marketplace add pluginagentmarketplace/custom-plugin-react/plugin install react-developer-roadmap@pluginagentmarketplace-reactThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/config.yamlreferences/GUIDE.mdscripts/helper.pyMaster React Router v6 for building single-page applications with client-side routing, including nested routes, protected routes, and navigation patterns.
npm install react-router-dom
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:userId" element={<UserProfile />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
}
import { Link, NavLink } from 'react-router-dom';
function Nav() {
return (
<nav>
<Link to="/">Home</Link>
<NavLink to="/about" className={({ isActive }) => isActive ? 'active' : ''}>
About
</NavLink>
</nav>
);
}
import { useNavigate } from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
const handleSubmit = async (credentials) => {
await login(credentials);
navigate('/dashboard'); // Navigate after login
// navigate(-1); // Go back
// navigate('/home', { replace: true }); // Replace history
};
return <form onSubmit={handleSubmit}>...</form>;
}
import { useParams } from 'react-router-dom';
// Route: /users/:userId
function UserProfile() {
const { userId } = useParams();
return <div>User ID: {userId}</div>;
}
// Multiple params: /posts/:postId/comments/:commentId
function Comment() {
const { postId, commentId } = useParams();
// ...
}
import { useSearchParams } from 'react-router-dom';
function ProductList() {
const [searchParams, setSearchParams] = useSearchParams();
const category = searchParams.get('category') || 'all';
const sort = searchParams.get('sort') || 'name';
const updateCategory = (newCategory) => {
setSearchParams({ category: newCategory, sort });
};
return (
<div>
{/* URL: /products?category=electronics&sort=price */}
<select value={category} onChange={(e) => updateCategory(e.target.value)}>
<option value="all">All</option>
<option value="electronics">Electronics</option>
</select>
</div>
);
}
import { Outlet } from 'react-router-dom';
function DashboardLayout() {
return (
<div>
<DashboardNav />
<main>
<Outlet /> {/* Child routes render here */}
</main>
</div>
);
}
// Route configuration
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
import { Navigate, useLocation } from 'react-router-dom';
function ProtectedRoute({ children }) {
const { user } = useAuth();
const location = useLocation();
if (!user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
}
// Usage
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>
import { lazy, Suspense } from 'react';
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
function App() {
return (
<Suspense fallback={<Spinner />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
);
}
import { useRouteError, isRouteErrorResponse } from 'react-router-dom';
function RouteErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
if (error.status === 404) {
return <NotFoundPage />;
}
return <ErrorPage status={error.status} message={error.statusText} />;
}
return <ErrorPage message="Something went wrong" />;
}
// Router configuration with error handling
const router = createBrowserRouter([
{
path: '/',
element: <RootLayout />,
errorElement: <RouteErrorBoundary />,
children: [/* routes */],
},
]);
function lazyWithRetry(importFn, retries = 3) {
return lazy(async () => {
for (let i = 0; i < retries; i++) {
try {
return await importFn();
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
}
}
});
}
const Dashboard = lazyWithRetry(() => import('./Dashboard'));
import { render, screen } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
describe('Routing', () => {
it('renders correct route', () => {
render(
<MemoryRouter initialEntries={['/dashboard']}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</MemoryRouter>
);
expect(screen.getByText(/dashboard/i)).toBeInTheDocument();
});
});
Version: 2.0.0 Last Updated: 2025-12-30 SASMP Version: 2.0.0 Difficulty: Intermediate Estimated Time: 1-2 weeks Prerequisites: React Fundamentals Changelog: Added error boundaries, lazy retry, and test templates
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.