为何页面刷新时React的App.js会渲染3次?
页面刷新时App.js的return语句执行3次的问题
页面首次登录加载时,App.js里的return语句执行2次符合预期,但刷新页面时会跑3次,搞不懂原因。下面是相关代码:
Index.js 代码
import React from "react"; import ReactDOM from "react-dom/client"; import { BrowserRouter } from "react-router-dom"; import "assets/plugins/nucleo/css/nucleo.css"; import "@fortawesome/fontawesome-free/css/all.min.css"; import "assets/scss/argon-dashboard-react.scss"; import { Auth0ProviderWithNavigate } from "./auth0-provider-with-navigate"; import { App } from "./app"; import store from "./app/store"; import { Provider } from "react-redux"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <BrowserRouter> <Auth0ProviderWithNavigate> <Provider store={store}> {console.log("Hit from Index")} <App /> </Provider> </Auth0ProviderWithNavigate> </BrowserRouter> );
App.js 代码
import { useAuth0 } from "@auth0/auth0-react"; import React, { useEffect } from "react"; import { Route, Routes } from "react-router-dom"; import { AuthenticationGuard } from "./components/authentication-guard"; import Admin from "layouts/Admin.js"; import Auth from "layouts/Auth.js"; export const App = () => { const { isLoading } = useAuth0(); useEffect(() => { console.log("Hit from App UseEffect"); }, []); return ( <> {console.log("Hit from App Return", isLoading)} {isLoading ? ( <div className="page-layout"> <Auth /> </div> ) : ( <Routes> <Route path="/" element={<Auth />} exact /> <Route path="/auth/*" element={<Auth />} /> <Route path="/admin/*" element={<AuthenticationGuard component={Admin} />} /> </Routes> )} </> ); };
问题原因和解决办法
为啥会多执行一次?
- React严格模式的影响:如果你的项目是Create React App这类默认开启严格模式的,开发环境下React会额外渲染一次组件,用来检测代码里的副作用问题。这会让return里的console.log多触发一次,刷新时就从2次变3次。
- Auth0状态变化触发重渲染:刷新页面时,Auth0的
isLoading会从true切换为false,触发一次重渲染;加上严格模式的额外渲染,刚好三次。首次登录时因为Auth0可能缓存了状态,状态变化次数更少,所以只执行2次。 - 外层Provider的初始化重渲染:
Auth0ProviderWithNavigate或Redux的Provider在刷新时会初始化内部状态,间接导致App组件重新渲染。
怎么处理?
- 确认严格模式:看看Index.js里有没有
<React.StrictMode>包裹,开发环境下的双重渲染是正常调试机制,生产环境会自动关闭,无需担心。 - 调整日志位置:别在return里放console.log,因为return里的代码每次渲染都会执行。把日志移到
useEffect里,按状态变化触发:useEffect(() => { console.log("App渲染完成,isLoading状态:", isLoading); }, [isLoading]); // 只有isLoading变化时才打印日志 - 优化组件渲染逻辑:可以结合
isAuthenticated和isLoading减少不必要的分支判断,或者用React.memo包裹App组件(不过因为依赖Auth0状态,memo的优化效果可能有限)。
总结
开发环境下的严格模式是额外渲染的主要原因,属于React的调试特性,生产环境不会有这个问题。如果嫌日志干扰,调整日志的放置位置即可,不要直接写在return语句中。
内容的提问来源于stack exchange,提问作者Noki
相关产品推荐
相关产品推荐

