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

Next.js项目引入GrapesJS遇TypeError: Cannot read properties of null错误

在Next.js中集成GrapesJS时出现TypeError: Cannot read properties of null (reading 'querySelector')的解决方案

问题背景

在Next.js项目中引入GrapesJS编辑器时触发错误:TypeError: Cannot read properties of null (reading 'querySelector'),推测原因是GrapesJS初始化时需要定位#gjs容器,但此时DOM尚未完成渲染,无法找到对应元素。

现有代码

Editor.js组件代码

import React, { useEffect, useState } from "react";
import grapesjs from "grapesjs";

const Editor = () => {
  const [editor, setEditor] = useState(null);

  useEffect(() => {
    const editor = grapesjs.init({
      container: "#gjs",
    });

    setEditor(editor);
  }, []);

  return (
    <>
      <div id="gjs"></div>
    </>
  );
};

export default Editor;

/editor路由页面代码

import { getSession } from "next-auth/react";
import "../i18n/config/config";
import "grapesjs/dist/css/grapes.min.css";
import dynamic from "next/dynamic";
import Editor from "../features/Editor/components/Editor";

// const EditorComponent = dynamic(
//   () => import("../features/Editor/components/Editor"),
//   {
//     ssr: false,
//   }
// );

export default function Home() {
  return <Editor />;
}

export async function getServerSideProps(context) {
  const session = await getSession(context);

  return {
    props: {
      session,
    },
  };
}

已尝试但无效的方案

  • 尝试动态导入Editor组件(禁用SSR),未生效
  • 在页面中添加全局<script src="//unpkg.com/grapesjs"></script>并移除组件内的import grapesjs from "grapesjs",项目可运行但控制台仍会出现该错误,对应页面代码如下:
import { getSession } from "next-auth/react";
import "../i18n/config/config";
import "grapesjs/dist/css/grapes.min.css";
import dynamic from "next/dynamic";
import Editor from "../features/Editor/components/Editor";

// const EditorComponent = dynamic(
//   () => import("../features/Editor/components/Editor"),
//   {
//     ssr: false,
//   }
// );

export default function Home() {
  return (
    <>
      <script src="//unpkg.com/grapesjs"></script>

      <Editor />
    </>
  );
}

export async function getServerSideProps(context) {
  const session = await getSession(context);

  return {
    props: {
      session,
    },
  };
}

错误截图

错误截图

解决方案

1. 修改Editor组件:使用Ref获取DOM节点而非ID选择器

避免依赖全局ID选择器,改用React的useRef直接获取DOM元素,同时确保仅在客户端环境初始化GrapesJS:

import React, { useEffect, useState, useRef } from "react";
import grapesjs from "grapesjs";

const Editor = () => {
  const [editor, setEditor] = useState(null);
  const gjsContainer = useRef(null);

  useEffect(() => {
    // 仅在客户端且DOM节点存在时初始化
    if (typeof window !== 'undefined' && gjsContainer.current) {
      const editorInstance = grapesjs.init({
        container: gjsContainer.current,
      });
      setEditor(editorInstance);

      // 组件卸载时销毁编辑器,防止内存泄漏
      return () => {
        editorInstance.destroy();
      };
    }
  }, []);

  return <div ref={gjsContainer} id="gjs"></div>;
};

export default Editor;

2. 页面中正确启用动态导入(禁用SSR)

由于页面使用了getServerSideProps(服务端渲染),必须确保Editor组件仅在客户端渲染,因此需要移除直接导入,改用动态导入:

import { getSession } from "next-auth/react";
import "../i18n/config/config";
import "grapesjs/dist/css/grapes.min.css";
import dynamic from "next/dynamic";

// 动态导入Editor组件,禁用服务端渲染
const Editor = dynamic(
  () => import("../features/Editor/components/Editor"),
  {
    ssr: false,
  }
);

export default function Home() {
  return <Editor />;
}

export async function getServerSideProps(context) {
  const session = await getSession(context);

  return {
    props: {
      session,
    },
  };
}

方案说明

  • 使用useRef直接绑定DOM节点,避免了ID选择器在服务端渲染时找不到元素的问题
  • 动态导入并禁用SSR,确保GrapesJS的初始化代码仅在浏览器环境执行
  • 添加编辑器销毁的清理函数,避免内存泄漏

内容的提问来源于stack exchange,提问作者KarimHesham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:45:38