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
相关推荐
小周同学@30 分钟前
谈谈对this的理解
开发语言·前端·javascript
Wiktok33 分钟前
Pyside6加载本地html文件并实现与Javascript进行通信
前端·javascript·html·pyside6
一只小风华~37 分钟前
Vue:条件渲染 (Conditional Rendering)
前端·javascript·vue.js·typescript·前端框架
柯南二号39 分钟前
【大前端】前端生成二维码
前端·二维码
程序员码歌1 小时前
明年35岁了,如何破局?说说心里话
android·前端·后端
博客zhu虎康2 小时前
React Hooks 报错?一招解决useState问题
前端·javascript·react.js
灰海2 小时前
vue中通过heatmap.js实现热力图(多个热力点)热区展示(带鼠标移入弹窗)
前端·javascript·vue.js·heatmap·heatmapjs
王源骏3 小时前
LayaAir鼠标(手指)控制相机旋转,限制角度
前端
大虾写代码3 小时前
vue3+TS项目配置Eslint+prettier+husky语法校验
前端·vue·eslint
wordbaby3 小时前
用 useEffectEvent 做精准埋点:React analytics pageview 场景的最佳实践与原理剖析
前端·react.js