nextjs中怎么正确使用@wangEditor富文本

背景

实现一个博客主站的文章生成系统,使用ssr去生成自己的文章,达到seo的效果。

技术栈

使用

  1. 引入富文本编辑器 npm i -S @wangeditor/editor @wangeditor/editor-for-react

  2. 基本的组件引入 src/app/components/rich-text/index.tsx 需要开启use client 可以试试不开,最后会贴上碰到的问题,以及解决方案

typescript 复制代码
// 不加报错 useState only works in Client Components. Add the "use client" directive at the top of the file to use it
'use client'
import { IDomEditor, IEditorConfig, IToolbarConfig } from '@wangeditor/editor';
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import '@wangeditor/editor/dist/css/style.css';
import React, { useEffect, useState } from 'react';
import './index.scss';

export interface IRichTextProps {
  /**
   * 富文本内容
   * @default ''
   */
  defaultContent?: string;
  /**
   * 富文本提示文字
   * @default '请输入内容'
   */
  placeholder?: string;
  /**
   * 富文本内容变化回调
   * @param html 富文本内容
   */
  onChange?: (html: string) => void;
}

export default function RichText(props: IRichTextProps) {
  const { defaultContent = '', placeholder = '请输入内容', onChange } = props;
  // editor 实例
  const [editor, setEditor] = useState<IDomEditor | null>(null);
  // 编辑器内容
  const [html, setHtml] = useState(defaultContent);
  // 工具栏配置
  const toolbarConfig: Partial<IToolbarConfig> = {};
  // 编辑器配置
  const editorConfig: Partial<IEditorConfig> = {
    placeholder
  };
  // 及时销毁 editor ,重要!
  useEffect(() => {
    return () => {
      if (editor === null) return;
      editor.destroy();
      setEditor(null);
    };
  }, [editor]);

  const handleChange = (editor: IDomEditor) => {
    const h = editor.getHtml();
    setHtml(h);
    onChange && onChange(h);
  };    

  return (
    <>
      <div style={{ border: '1px solid #ccc', zIndex: 100 }}>
        <Toolbar
          editor={editor}
          defaultConfig={toolbarConfig}
          mode="default"
          style={{ borderBottom: '1px solid #ccc' }}
        />
        <Editor
          defaultConfig={editorConfig}
          value={html}
          onCreated={setEditor}
          onChange={handleChange}
          mode="default"
        />
      </div>
    </>
  );
}
  1. 页面中的使用 目录: src/app/rich/page.tsx
typescript 复制代码
import dynamic from 'next/dynamic'
import { Metadata } from 'next';

// 关闭服务端渲染 否则报错 ReferenceError: Element is not defined
const RichText = dynamic(() => import("../components/rich-text"), {
  ssr: false,
});

export const metadata: Metadata = {
  title: '创建数据',
}

export default function CreateText() {
  return (
    <div className='a'>
        <RichText />
    </div>
  );
}
  1. 以上基本上代码层面没问题了,问题会出现在第三方插件和nextjs集成的一些地方

问题

针对性的说一下wangeditor和nextjs一起使用出现的问题

  1. TypeError: Cannot set property navigator of #<Object> which has only a getter 问题描述:nextjs内部对全局navigator对象通过重新定义api(defineProperty),该值被设置为不可更改,只能读;而wangeditor内部却在更改navigator这个值,导致报错提示 解决方案:找到node_modules中wangeditor/editor中dist的index.esm.js删除掉更改navigator的代码 ---- 后面会给出文件
  2. TypeError: t is not function 来自于@wangEditor/editor的报错 解决方案:找到对应报错的index.esm.js中的地方,处理一下代码即可 --- 后面会给出文件
  3. Cannot destructure property 'protocol' of 'window.location' as it is undefined. 问题描述:由问题1引发的问题,解决问题1即可
  4. ⨯ ReferenceError: Element is not defined 问题描述:由于在服务端渲染@wangEditor插件导致,按照上面代码使用,就不会出现此问题

以上的统一解决方案

核心思路:替换更改后的index.esm.js作为构建的资源, 打开下方在线编辑器-进入获取js文件内容

标题在根目录下创建scripts文件夹,然后新建run.sh
markdown 复制代码
`run.sh` *(这里博主以pnpm包管理器为例,如果你们是yarn和npm需要自己找到对应的依赖包做替换。)*
bash 复制代码
cp scripts/index.esm.js node_modules/.pnpm/@wangeditor+editor@5.1.23/node_modules/@wangeditor/editor/dist/index.esm.js
相关推荐
GISer_Jing1 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪2 小时前
CSS复习
前端·css
咖啡の猫4 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5817 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路7 小时前
GeoTools 读取影像元数据
前端
ssshooter8 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal9 小时前
关于RSA和AES加密
前端·vue.js
柳杉9 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化