React根容器加载失败排查:已加root仍报错及Keycloak集成问题
React集成Keycloak(react-oidc-context)遇到的DOM容器错误及路由配置问题
我是React新手,正在尝试用react-oidc-context把React应用集成到Keycloak服务器,需求是/dashboard路由需要认证才能访问,/about-us设为公开访问。已经在index.html里加了<div id="root"></div>,但运行npm start后访问http://localhost:3000时出现「Target container is not a DOM element」错误。以下是项目结构、代码和报错信息,求排查:
项目结构
myapp/ public/ index.html src/ index.jsx main/ Dashboard.jsx web/ AboutUs.jsx
相关代码
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html>
index.jsx
import React from "react"; import ReactDOM from "react-dom"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { AuthProvider } from "react-oidc-context"; import Dashboard from "./main/Dashboard"; import AboutUs from "./web/AboutUs"; import AccountSettings from "./main/AccountSettings"; const oidcConfig = { authority: process.env.REACT_APP_KEYCLOAK_REALM, client_id: process.env.REACT_APP_KEYCLOAK_CLIENT, redirect_uri: process.env.REACT_APP_KEYCLOK_REDIRECT_URL }; ReactDOM.render( <Router> <AuthProvider {...oidcConfig}> <Routes> <Route path="/dashboard" element={<Dashboard />} /> </Routes> </AuthProvider> <Routes> <Route path="/about-us" element={<AboutUs />} /> </Routes> </Router>, document.getElementById("app") );
Dashboard.jsx
import React from "react"; import { useAuth } from "react-oidc-context"; function Dashboard() { const auth = useAuth(); switch (auth.activeNavigator) { case "signinSilent": return <div>Signing you in...</div>; case "signoutRedirect": return <div>Signing you out...</div>; } if (auth.isLoading) { return <div>Loading Dashboard...</div>; } if (auth.error) { return <div>Oops... {auth.error.message}</div>; } if (auth.isAuthenticated) { return ( <div> Hello {auth.user?.profile.sub}{" "} welcome to the Dashboard! <button onClick={() => void auth.removeUser()}>Log out</button> </div> ); } return <button onClick={() => void auth.signinRedirect()}>Log in</button>; } export default Dashboard;
报错信息
ERROR Target container is not a DOM element. at Object.render (http://localhost:3000/static/js/bundle.js:35922:15) at ./src/index.jsx (http://localhost:3000/static/js/bundle.js:39:40) at options.factory (http://localhost:3000/static/js/bundle.js:52145:31) at __webpack_require__ (http://localhost:3000/static/js/bundle.js:51566:32) at http://localhost:3000/static/js/bundle.js:52722:37 at http://localhost:3000/static/js/bundle.js:52724:12
另外刷新页面时Chrome开发者工具显示大量304状态码。
问题排查及解决方案
1. 「Target container is not a DOM element」错误修复
你的index.jsx里用document.getElementById("app")获取挂载容器,但index.html中定义的容器ID是root,两者不匹配导致React找不到DOM元素。
修改代码:
将index.jsx中的挂载目标改为root:
ReactDOM.render( <Router> {/* 其余代码保持不变 */} </Router>, document.getElementById("root") // 此处修改为root );
2. 路由配置优化(满足认证/公开需求)
当前代码拆分了两个Routes组件,不符合React Router的规范,同时可以优化认证路由的保护逻辑:
推荐方案:全局AuthProvider+认证路由组件
创建一个通用的ProtectedRoute组件统一处理认证逻辑,适用于多个需要认证的路由场景:
- 创建
src/ProtectedRoute.jsx:
import React from "react"; import { useAuth } from "react-oidc-context"; import { Navigate } from "react-router-dom"; function ProtectedRoute({ children }) { const auth = useAuth(); if (auth.isLoading) { return <div>Loading...</div>; } if (!auth.isAuthenticated) { auth.signinRedirect(); return <div>Redirecting to login...</div>; } return children; } export default ProtectedRoute;
- 修改
index.jsx:
import React from "react"; import ReactDOM from "react-dom"; import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom"; import { AuthProvider } from "react-oidc-context"; import Dashboard from "./main/Dashboard"; import AboutUs from "./web/AboutUs"; import ProtectedRoute from "./ProtectedRoute"; // 注意:修复环境变量名拼写错误(KEYCLOK → KEYCLOAK) const oidcConfig = { authority: process.env.REACT_APP_KEYCLOAK_REALM, client_id: process.env.REACT_APP_KEYCLOAK_CLIENT, redirect_uri: process.env.REACT_APP_KEYCLOAK_REDIRECT_URL }; ReactDOM.render( <AuthProvider {...oidcConfig}> <Router> <Routes> {/* 公开路由 */} <Route path="/about-us" element={<AboutUs />} /> {/* 受保护的认证路由 */} <Route path="/dashboard" element={ <ProtectedRoute> <Dashboard /> </ProtectedRoute> } /> {/* 默认路由重定向到公开页面 */} <Route path="/" element={<Navigate to="/about-us" />} /> </Routes> </Router> </AuthProvider>, document.getElementById("root") );
3. 其他注意事项
- 你的
oidcConfig中redirect_uri对应的环境变量名拼写错误:REACT_APP_KEYCLOK_REDIRECT_URL应改为REACT_APP_KEYCLOAK_REDIRECT_URL,否则会导致Keycloak回调失败。 - 304状态码是浏览器缓存机制导致的正常现象,若需强制刷新缓存,可运行
npm start -- --no-cache。
内容的提问来源于stack exchange,提问作者hotmeatballsoup
相关产品推荐
相关产品推荐

