在Next.js中使用react-org-chart报错:document is not defined
解决Next.js中react-org-chart的"document is not defined"错误及替代组件建议
错误原因
react-organizational-chart组件在服务端渲染阶段会尝试访问浏览器环境的document对象,但Next.js的服务端环境不存在该对象,因此触发报错。
解决方案
方案1:动态导入组件并禁用SSR
使用Next.js的dynamic导入功能,将react-org-chart组件设置为仅在客户端渲染:
import dynamic from 'next/dynamic'; import SidebarDesktop from "../components/layout/sidebarDesktop"; import SidebarMobile from "../components/layout/sidebarMobile"; import StickyHeader from "../components/layout/stickyHeader"; import navigationList from "../components/layout/navigationList"; import React from "react"; // 动态导入,禁用服务端渲染 const { Tree, TreeNode } = dynamic( () => import('react-organizational-chart'), { ssr: false } ); export default function OrganizationalChart() { return ( <div> <SidebarMobile menu={navigationList()} loc={asPath} /> <SidebarDesktop menu={navigationList()} loc={asPath} /> <div className="md:pr-52 flex flex-col flex-1"> <StickyHeader /> <main className="py-10 space-y-6"> <Tree label="Root" lineBorderRadius="10px" lineColor="green" lineHeight="30px" lineWidth="3px" > <TreeNode label={<div>Child 1</div>}> <TreeNode label={<div>Grand Child</div>} /> </TreeNode> <TreeNode label={<div>Child 2</div>}> <TreeNode label={<div>Grand Child</div>}> <TreeNode label={<div>Great Grand Child 1</div>} /> <TreeNode label={<div>Great Grand Child 2</div>} /> </TreeNode> </TreeNode> <TreeNode label={<div>Child 3</div>}> <TreeNode label={<div>Grand Child 1</div>} /> <TreeNode label={<div>Grand Child 2</div>} /> </TreeNode> </Tree> </main> </div> </div> ); }
方案2:条件渲染,仅在客户端加载组件
通过useEffect判断客户端环境,再渲染组织结构图:
import SidebarDesktop from "../components/layout/sidebarDesktop"; import SidebarMobile from "../components/layout/sidebarMobile"; import StickyHeader from "../components/layout/stickyHeader"; import navigationList from "../components/layout/navigationList"; import { Tree, TreeNode } from "react-organizational-chart"; import React, { useState, useEffect } from "react"; export default function OrganizationalChart() { const [isClient, setIsClient] = useState(false); useEffect(() => { // 组件挂载后确认处于客户端环境 setIsClient(true); }, []); return ( <div> <SidebarMobile menu={navigationList()} loc={asPath} /> <SidebarDesktop menu={navigationList()} loc={asPath} /> <div className="md:pr-52 flex flex-col flex-1"> <StickyHeader /> <main className="py-10 space-y-6"> {/* 仅在客户端渲染Tree组件 */} {isClient && ( <Tree label="Root" lineBorderRadius="10px" lineColor="green" lineHeight="30px" lineWidth="3px" > <TreeNode label={<div>Child 1</div>}> <TreeNode label={<div>Grand Child</div>} /> </TreeNode> <TreeNode label={<div>Child 2</div>}> <TreeNode label={<div>Grand Child</div>}> <TreeNode label={<div>Great Grand Child 1</div>} /> <TreeNode label={<div>Great Grand Child 2</div>} /> </TreeNode> </TreeNode> <TreeNode label={<div>Child 3</div>}> <TreeNode label={<div>Grand Child 1</div>} /> <TreeNode label={<div>Grand Child 2</div>} /> </TreeNode> </Tree> )} </main> </div> </div> ); }
替代组件建议
如果react-org-chart的兼容性问题难以解决,可以考虑以下更适配Next.js的组件:
- @dnd-kit/react-tree:支持拖拽排序的树形组件,适合需要交互的组织结构场景,对SSR支持良好,配置灵活。
- react-tree-graph:轻量级SVG树形图组件,自定义性强,服务端渲染兼容无压力,适合静态或简单交互的组织结构展示。
- 自定义CSS布局:若组织结构层级简单,可直接用CSS Grid/Flexbox手动实现布局,完全控制渲染逻辑,避免第三方组件的环境兼容问题。
内容的提问来源于stack exchange,提问作者Pou4a
相关产品推荐
相关产品推荐

