未启用StrictMode时,Router组件中Switch外部无路由组件首次加载重复渲染两次的问题排查
Problem Description
I have a Router component where I placed a <Component /> above the Switch so it renders at the top of all route pages. The issue is: this component renders twice on initial app load only (not when switching routes). Notes:
<Component />is a functional component that only returns another component based on conditions.- I have not enabled StrictMode.
- My App.js only returns the RouterApp wrapped in styled-components' ThemeProvider.
Here's my code:
const RouterApp = (props) => { const renderPublicRoute = (path, ComponentToRender, exact = true) => { return ( <Route exact={exact} path={path} render={props => <ComponentToRender {...props} />} /> ); } return ( <Router> <Component /> {/* <--- The problematic component */} <Switch> {renderPublicRoute('/path', OnboardingScreen)} {renderPublicRoute('/anotherpath', TermsScreen)} {/* ... other routes ... */} </Switch> </Router> ); } export default RouterApp;
Answer
Let’s break down the most likely causes and how to fix them:
1. You might have hidden StrictMode in your component tree
Even if you didn’t wrap RouterApp in StrictMode, check the root of your application (usually index.js). Many React scaffolding tools like Create React App automatically add <StrictMode> around the root component in development mode. For example:
// index.js (common hidden StrictMode location) const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <StrictMode> {/* This is easy to miss! */} <ThemeProvider theme={yourTheme}> <RouterApp /> </ThemeProvider> </StrictMode> );
StrictMode intentionally double-invokes render functions (and hooks like useState, useEffect) in development to help detect unintended side effects. If this is the case, removing <StrictMode> will stop the double render (note: this only affects development builds—StrictMode is disabled in production).
2. <Component /> has internal state updates triggering a re-render
Check if your <Component /> is updating state immediately during its initial render. For example:
- Directly calling
setStatein the component function body (outside of hooks) - An
useEffectwith an empty dependency array that updates state - Conditional logic that modifies state during rendering
This would cause the component to render once, then immediately re-render when the state changes. To debug this:
- Add a
console.log('Component rendered')at the top of<Component /> - Add
console.log('RouterApp rendered')at the top ofRouterApp- If both log twice: The parent
RouterAppis re-rendering, so look for state changes in its parent components or StrictMode. - Only
<Component />logs twice: The issue is inside<Component />itself—trace down any state updates that fire on initial load.
- If both log twice: The parent
3. Unlikely: React Router's initial setup logic
In rare cases, React Router might trigger a small internal state update during initialization that causes the Router component to re-render once. However, this would usually affect all components inside the Router, not just your top-level <Component />. This is the least probable cause, so rule out the first two before investigating this.
Quick Code Optimization
While not related to the double render issue, you can simplify your renderPublicRoute function by using the component prop instead of render—it’s cleaner and avoids unnecessary function creation:
const renderPublicRoute = (path, ComponentToRender, exact = true) => { return ( <Route exact={exact} path={path} component={ComponentToRender} /> ); }
内容的提问来源于stack exchange,提问作者Wrathgore

