跪拜 Guibai
← All articles
React.js · Interviews · Frontend Frameworks

The One Question That Prevents Most React Router Layout Bugs

By 烬羽 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Nested-route layout bugs are among the most common React Router mistakes because the framework silently renders parent UI into every child. Knowing the rule—"if it doesn't belong on every child page, it doesn't belong in the parent"—eliminates an entire class of layout regressions before they reach QA.

Summary

A common React Router mistake puts shared UI in a parent layout component and then discovers it bleeding into child pages that shouldn't display it. The `<Outlet />` slot renders the matched child route inside the parent, but the parent's own markup—headings, sidebars, navigation—renders unconditionally for every child. The fix is a placement rule: parent routes hold only the framework that every single child needs; page-specific UI belongs in the child component itself.

When a piece of UI appears on a page where it makes no sense, the diagnostic is straightforward. The parent component treats all children equally and has no mechanism to selectively hide its markup. Moving that UI into the specific child component that requires it eliminates the leak. If duplication emerges later across multiple children, the UI can be lifted back into the parent—the same mental model as lifting state.

The article walks through a concrete example of an e-commerce admin where a "Product List" heading shows up on the "Add New Product" form. The solution is a one-line move, but the underlying principle generalizes to every nested-route layout decision in React Router.

Takeaways
An `<Outlet />` renders the matched child route into the parent component, but the parent's own JSX renders unconditionally for every child.
UI that is not needed by every child route must live in the specific child component, not in the parent layout.
Start with all UI in child routes and lift shared pieces into the parent only when duplication appears—the same pattern as lifting React state.
Route-based code splitting with `lazy()` and `Suspense` keeps page bundles from loading until the user navigates to them.
A catch-all `path="*"` route must be the last entry in `<Routes>` because React Router matches top-to-bottom.
Conclusions

The parent-child UI ownership problem in React Router is structurally identical to state lifting in React, but developers often miss the analogy because layout feels like a separate concern from data flow.

The diagnostic question—"Does this UI appearing on every child page make sense?"—is a cheap, reliable heuristic that catches layout bugs at design time rather than at runtime.

Treating the parent route as a pure `<Outlet />` container with zero shared UI is a valid starting strategy that eliminates false sharing and forces explicit decisions about what truly belongs in the layout.

Concepts & terms
Outlet
A React Router component that acts as a placeholder in a parent route's component tree. The currently matched child route's element renders into this slot, while the rest of the parent's JSX renders unconditionally.
Nested Routes
A React Router pattern where `<Route>` elements are nested inside a parent `<Route>`, creating a component hierarchy where the parent renders first and the matched child renders into the parent's `<Outlet />`.
Route-based code splitting
Using React's `lazy()` and `Suspense` to load page components only when their route is visited, reducing the initial JavaScript bundle size for applications with many pages.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗