You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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组件统一处理认证逻辑,适用于多个需要认证的路由场景:

  1. 创建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;
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 01:30:32