Next.js自定义API上传图片后嵌入CKEditor5显示异常问题
问题解决方案
解决CKEditor显示[object Object]的问题
你当前的核心问题是把JSX元素直接和字符串拼接,JSX本质是React.createElement返回的对象,转成字符串自然会显示[object Object]。CKEditor的data属性接收的是HTML字符串而非JSX对象,以下是两种修复方案:
方案1:拼接纯HTML字符串(简单直接)
修改handleUpload中的图片拼接逻辑,生成HTML字符串而非JSX,同时用函数式更新避免闭包问题:
const handleUpload = async () => { const fileInput = document.getElementById('file-upload'); if (fileInput && fileInput.files.length > 0) { const formData = new FormData(); const files = Array.from(fileInput.files); files.forEach((file, index) => { formData.append("files", fileInput.files[index], file.name); }); formData.append("folderName", "community/question"); try { const uploadImage = await communityDTO.uploadImage(formData); if (uploadImage) { const uploadedUrls = typeof uploadImage.uploadedUrls === 'string' ? [uploadImage.uploadedUrls] : uploadImage.uploadedUrls; // 生成HTML字符串 const imgHtmls = uploadedUrls.map(item => `<img class="my-2" src="${item}" alt="Image ${item}" />` ).join('\n'); // 函数式更新获取最新的inputBody值 setInputBody(prev => `${prev}\n${imgHtmls}`); } } catch (error) { console.error('Error:', error); } } else { console.error('No files selected'); } };
方案2:用CKEditor实例插入内容(更规范)
直接操作编辑器实例插入图片,能更好兼容编辑器内部状态,避免手动拼接HTML的潜在问题:
- 先通过
useRef获取CKEditor实例:
import { useRef } from 'react'; // ... const editorRef = useRef(null); <CKEditor editor={ClassicEditor} data={inputBody} onReady={(editor) => { editorRef.current = editor; // 保存编辑器实例 }} onChange={(event, editor) => { const data = editor.getData(); setInputBody(data); }} // 其他原有配置... />
- 修改
handleUpload,用编辑器API插入图片:
const handleUpload = async () => { const fileInput = document.getElementById('file-upload'); if (fileInput && fileInput.files.length > 0 && editorRef.current) { const formData = new FormData(); const files = Array.from(fileInput.files); files.forEach((file, index) => { formData.append("files", fileInput.files[index], file.name); }); formData.append("folderName", "community/question"); try { const uploadImage = await communityDTO.uploadImage(formData); if (uploadImage) { const uploadedUrls = typeof uploadImage.uploadedUrls === 'string' ? [uploadImage.uploadedUrls] : uploadImage.uploadedUrls; const editor = editorRef.current; // 逐个插入图片到编辑器光标位置 uploadedUrls.forEach(item => { const imgElement = editor.model.createElement('imageBlock', { src: item, alt: `Image ${item}` }); editor.model.insertContent(imgElement, editor.model.document.selection); // 手动设置margin样式 editor.model.change(writer => { writer.setStyle('margin-top', '0.5rem', imgElement); writer.setStyle('margin-bottom', '0.5rem', imgElement); }); }); // 同步更新inputBody setInputBody(editor.getData()); } } catch (error) { console.error('Error:', error); } } else { console.error('No files selected or editor not ready'); } };
CKEditor免费版支持Markdown图片语法的方法
CKEditor 5免费版(ClassicEditor)默认基于HTML,但可以通过安装Markdown插件支持类似StackOverflow的语法(注意是感叹号开头,这是标准Markdown图片语法):
- 安装Markdown插件:
npm install @ckeditor/ckeditor5-markdown-gfm
- 修改CKEditor的导入和配置,启用Markdown支持:
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; import Markdown from '@ckeditor/ckeditor5-markdown-gfm/src/markdown'; // 保留你原有的其他插件(如Bold、Italic等) <CKEditor editor={ClassicEditor} data={inputBody} onChange={(event, editor) => { const data = editor.getData(); // 此时data为Markdown格式 setInputBody(data); }} config={{ plugins: [Markdown, /* 你的其他插件:Bold, Italic, BlockQuote等 */], toolbar: { items: [ "undo", "redo", "|", "bold", "italic", "blockQuote", "link", "numberedList", "bulletedList", "|", "heading" ], shouldNotGroupWhenFull: true, }, placeholder: "Write your Answer...", markdown: {} // 可添加自定义配置 }} />
- 上传图片后,可直接拼接Markdown格式字符串插入:
// 在handleUpload中替换为Markdown格式 const markdownImgs = uploadedUrls.map(item => `` ).join('\n'); setInputBody(prev => `${prev}\n${markdownImgs}`);
内容的提问来源于stack exchange,提问作者Dhruv
相关产品推荐
相关产品推荐

