在Next.js(React)中集成TinyMCE编辑器并在表单提交时获取内容
在Next.js的React项目中,通过表单提交获取TinyMCE编辑器内容的解决方案
你的代码存在两个核心问题:
- 定义了
editoruseRef但未绑定到Editor组件,反而使用未声明的setEditor尝试存储实例 - return语句中重复渲染了一个无配置的
<Editor />,导致实际交互的编辑器和你试图获取实例的不是同一个
以下是两种可行的修正方案:
方案一:使用useRef绑定编辑器实例(推荐)
通过ref属性直接将编辑器实例绑定到useRef,提交时调用getContent()获取内容:
import { useRef, FormEventHandler } from 'react'; import Editor from '@tinymce/tinymce-react'; export default function YourFormPage() { // 创建ref存储编辑器实例 const editorRef = useRef<any>(null); const handleSubmit: FormEventHandler<HTMLFormElement> = async (e) => { // 阻止表单默认提交行为,避免页面刷新丢失实例 e.preventDefault(); // 获取表单其他字段值 const name = e.target.name.value; const cat_name = e.target.cat_name.value; // 获取编辑器内容 if (editorRef.current) { const editorContent = editorRef.current.getContent(); console.log('编辑器内容:', editorContent); // 此处可添加提交到后端等业务逻辑 } }; return ( <> <form className="forms-sample" onSubmit={handleSubmit}> {/* 表单其他输入字段 */} <input type="text" name="name" placeholder="请输入名称" /> <input type="text" name="cat_name" placeholder="请输入分类名称" /> {/* 绑定ref的TinyMCE编辑器 */} <Editor ref={editorRef} initialValue="<p>This is the initial content of the editor.</p>" init={{ height: 500, menubar: false, plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen', 'insertdatetime media table paste code help wordcount' ], toolbar: 'undo redo | formatselect | ' + 'bold italic backcolor | alignleft aligncenter ' + 'alignright alignjustify | bullist numlist outdent indent | ' + 'removeformat | help', content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }' }} /> <button type="submit" className='btn btn-primary mr-2'>提交</button> </form> </> ); }
方案二:使用State存储编辑器实例
如果需要在组件其他逻辑中复用编辑器实例,可以通过onInit回调将实例存入state:
import { useState, FormEventHandler } from 'react'; import Editor from '@tinymce/tinymce-react'; // TypeScript可引入类型:import type { Editor as TinyMCEEditor } from 'tinymce'; export default function YourFormPage() { // 用state存储编辑器实例,TypeScript可指定类型:const [editorInstance, setEditorInstance] = useState<TinyMCEEditor | null>(null); const [editorInstance, setEditorInstance] = useState<any>(null); const handleSubmit: FormEventHandler<HTMLFormElement> = async (e) => { e.preventDefault(); const name = e.target.name.value; const cat_name = e.target.cat_name.value; if (editorInstance) { const editorContent = editorInstance.getContent(); console.log('编辑器内容:', editorContent); // 业务逻辑处理 } }; return ( <> <form className="forms-sample" onSubmit={handleSubmit}> <input type="text" name="name" placeholder="请输入名称" /> <input type="text" name="cat_name" placeholder="请输入分类名称" /> <Editor onInit={(evt, ed) => setEditorInstance(ed)} initialValue="<p>This is the initial content of the editor.</p>" init={{ height: 500, menubar: false, plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen', 'insertdatetime media table paste code help wordcount' ], toolbar: 'undo redo | formatselect | ' + 'bold italic backcolor | alignleft aligncenter ' + 'alignright alignjustify | bullist numlist outdent indent | ' + 'removeformat | help', content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }' }} /> <button type="submit" className='btn btn-primary mr-2'>提交</button> </form> </> ); }
关键注意事项
- 必须调用
e.preventDefault():否则表单默认提交会刷新页面,导致编辑器实例丢失,无法获取内容 - 仅渲染一个Editor组件:重复渲染会生成多个编辑器实例,导致获取的内容与交互的编辑器不匹配
- TypeScript类型优化:建议替换
any为TinyMCE的Editor类型,提升代码健壮性
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

