Skip to content

Part 7.2 — Advanced Routing Patterns: Protected Routes & URL State

Site Console Site Console
3 min read Updated Feb 3, 2026 Frontend Design 0 comments

Once routing fundamentals are in place, the next challenges are control and intent.

  • Who can access this route?

  • Where should users be redirected?

  • Which UI state belongs in the URL?

These are architectural questions—not just routing tricks. This post shows how to answer them cleanly with React Router.


1. Protected Routes Are About Boundaries

Protected routes exist to enforce access rules, not to hide UI.

Examples:

  • authenticated-only pages

  • admin-only screens

  • onboarding steps

The router should express these boundaries explicitly.


2. Avoid Guard Logic Inside Pages

Bad:

if (!user) {
  return <Navigate to="/login" />;
}

Scattered across components, this becomes brittle and inconsistent.


3. Create a Route Guard Component

Centralize access control:

function RequireAuth({ children }: { children: JSX.Element }) {
  const { user } = useAuthState();

  if (!user) {
    return <Navigate to="/login" replace />;
  }

  return children;
}

This keeps rules in one place.


4. Use Guards in Route Definitions

<Route
  path="/dashboard"
  element={
    <RequireAuth>
      <Dashboard />
    </RequireAuth>
  }
/>

Now:

  • access rules are explicit

  • routing structure reflects security boundaries


5. Redirect Back After Login

Preserve intent using location state:

function RequireAuth({ children }: { children: JSX.Element }) {
  const { user } = useAuthState();
  const location = useLocation();

  if (!user) {
    return (
      <Navigate
        to="/login"
        state={{ from: location }}
        replace
      />
    );
  }

  return children;
}

After login:

const from = location.state?.from?.pathname || '/';
navigate(from, { replace: true });

Users land where they originally intended.


6. Role-Based Access Control

Extend guards:

function RequireRole({
  role,
  children,
}: {
  role: 'admin' | 'user';
  children: JSX.Element;
}) {
  const { user } = useAuthState();

  if (!user || user.role !== role) {
    return <Navigate to="/403" replace />;
  }

  return children;
}

Routes communicate authorization clearly.


7. URL State: When State Belongs in the URL

Some UI state should live in the URL:

  • pagination

  • filters

  • search queries

  • sorting

  • selected tabs

If users expect:

  • shareable links

  • browser back/forward

  • refresh persistence

It belongs in the URL.


8. Managing Query Parameters Safely

const [params, setParams] = useSearchParams();

const page = Number(params.get('page') ?? 1);

Update URL state:

setParams({ page: String(page + 1) });

Treat query params like untrusted input:

  • parse

  • validate

  • provide defaults


9. Avoid Duplicating URL State in React State

Bad:

const [page, setPage] = useState(1);

Good:

const page = Number(searchParams.get('page') ?? 1);

The URL is the source of truth.


10. Combining URL State with Data Fetching

useEffect(() => {
  fetch(`/api/users?page=${page}`);
}, [page]);

This gives you:

  • bookmarkable pages

  • natural refetching

  • predictable lifecycle

Routing drives data—not the other way around.


11. Redirects as Architecture, Not Fixes

Redirects should be intentional:

  • //dashboard

  • /profile/settings/profile

Avoid using redirects to “fix” broken navigation.


12. Handling 404 and 403 Routes

Always define explicit routes:

<Route path="/403" element={<Forbidden />} />
<Route path="*" element={<NotFound />} />

Errors are part of UX—not afterthoughts.


13. Common Advanced Routing Mistakes

Watch for:

  • auth logic duplicated across components

  • UI state mirrored in URL and state

  • redirects hiding architectural issues

  • deeply nested guards

Routing should clarify intent—not obscure it.


14. Summary

You now know how to:

  • implement protected routes cleanly

  • centralize auth and role guards

  • preserve user intent on redirects

  • use URLs as state

  • manage query parameters safely

  • align routing with data fetching

Related

Leave a comment

Sign in to leave a comment.

Comments