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
相关推荐
阿征学IT8 分钟前
vue计算属性 初步使用案例
前端·javascript·vue.js
Qhumaing8 分钟前
html文本元素
前端·html
林太白10 分钟前
❤React-React 组件通讯
前端·javascript·react.js
码手Lion26 分钟前
CSS多列布局:打破传统布局的束缚
前端·css
青龙摄影34 分钟前
【自动化】学习观看视频内容,无需人为干预
前端·vue.js·elementui
豆华39 分钟前
React 中 为什么多个 JSX 标签需要被一个父元素包裹?
前端·react.js·前端框架
起风的秋天@44 分钟前
CSS Modules在框架中的使用
前端·css
前端熊猫44 分钟前
React第一个项目
前端·javascript·react.js
练习两年半的工程师44 分钟前
使用React和Vite构建一个AirBnb Experiences克隆网站
前端·react.js·前端框架
林太白1 小时前
❤React-JSX语法认识和使用
前端·react.js·前端框架