NextJS项目中需要使用CkEditor5作为富文本编辑器,按照官网React CkEditor5手册使用出现如下错误:
node_modules/@ckeditor/ckeditor5-react/dist/index.js (5:242) @ eval
⨯ ReferenceError: self is not defined
还是因为nextjs的服务器端渲染造成的错误,富文本编辑器一般用在表单提交页面,没有使用ssr的必要,想要解决上面问题,动态导入组件,禁用ssr就可以解决。
1、封装ckeditor组件
"use client"
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
export function CustomCkEditor(props: {data: string, onChange: (content: string)=>void}) {
const editorConfiguration = {
toolbar: [
'heading', //类型
'|',
'bold', //加粗
'italic', //斜体
'link', //超链接
'bulletedList',// 无序列表
'numberedList', //有序列表
'|',
'indent', //左缩进
'outdent', //右缩进
'|',
'imageUpload', //图片上传
'blockQuote', //引用
'insertTable', //插入图标
//'mediaEmbed', //视频上传
'undo', //撤销
'redo'//重做
]
};
return (
<CKEditor
config={ editorConfiguration }
editor={ ClassicEditor }
data={ props.data }
onReady={ editor => {
// You can store the "editor" and use when it is needed.
console.log( 'Editor is ready to use!', editor );
} }
onChange={ ( event, editor ) => {
const data = editor.getData();
props.onChange(data)
console.log( { event, editor, data } );
} }
onBlur={ ( event, editor ) => {
console.log( 'Blur.', editor );
} }
onFocus={ ( event, editor ) => {
console.log( 'Focus.', editor );
} }
/>
)
}
2、动态导入的Form组件
"use client"
import React from "react";
import { CustomCkEditor } from "@/components/app/custom-ckeditor";
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export function ReleaseForm(props: {})
{
const [title, setTitle] = React.useState("");
const [content, setContent] = React.useState("");
const buildCkEditor = () => {
return (
<div className="release-ckeditor w-full overflow-visible text-black">
<CustomCkEditor data={content} onChange={(data: string)=>setContent(data)}/>
</div>
)
}
const handleSubmit = () => {
}
return (
<>
<div className="mx-auto mt-5 lg:w-4/5 overflow-visible p-10 bg-white dark:bg-gray-900">
<div className="text-lg font-bold">发布帖子</div>
<div className="w-full mt-5">
<Label className=" text-base ">标题 <span className="ml-2 text-xs">(最多60字)</span></Label>
<Input value={title} placeholder="请输入标题" className="mt-1 focus-visible:ring-0" onChange={(e)=>{setTitle(e.target.value)}}/>
<div className="h-4 text-red-600 text-xs mt-1"></div>
</div>
<Label className=" text-base">内容</Label>
<div className=" h-1"></div>
{
buildCkEditor()
}
<div className="w-full text-center">
<Button className="mt-8 w-28" onClick={handleSubmit}>提交</CustomButton>
</div>
</div>
</>
)
}
3、导入Form、禁用ssr
"use client"
import React from "react";
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { CustomButton } from "@/components/app/custom-button";
import { ReleasePropsDialog } from "./(components)/release-props-dialog";
import dynamic from 'next/dynamic'
import { KeyPair } from "@/define/type";
//import { ReleaseForm } from "./(components)/release-form";
export default function ForumReleasePage({ params }: { params: { topic: string } }) {
//动态导入,禁用ssr,否则报错ReferenceError: self is not defined
const ReleaseForm = dynamic(() => import('./(components)/release-form').then((mod) => mod.ReleaseForm), { ssr: false })
return (
<>
<ReleaseForm/>
</>
)
}
注意:这里之所以把所有表单界面和表单业务操作封装到ReleaseForm组件内,是因为测试发现如果只是直接动态导入CustomCkEditor,当绑定的内容改变,动态组件就会重新加载刷新出现闪烁现象
网友评论