React中预加载CKEditor数据失败,求解决方案
解决React中CKEditor预加载数据的问题
你的核心问题在于用DOM操作传递数据、未正确管理CKEditor实例和数据的同步时机,以下是修正方案:
核心优化思路
- 放弃通过隐藏输入框传递数据的方式,改用React状态管理获取到的内容,避免DOM同步问题
- 用
useRef保存CKEditor实例,确保能在正确时机调用setData - 利用状态变化触发编辑器数据更新,而非依赖DOM操作
完整代码示例
import { useState, useLayoutEffect, useRef } from 'react'; import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; import { CKEditor } from '@ckeditor/ckeditor5-react'; import axios from 'axios'; function ReportEditor() { // 用状态存储从接口获取的数据 const [nota, setNota] = useState(''); const [tipo, setTipo] = useState(''); // 用ref保存CKEditor实例 const editorRef = useRef(null); // 获取URL参数并请求数据 useLayoutEffect(() => { const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const idBorrador = urlParams.get('tipo'); if (idBorrador) { const fetchData = async () => { try { const response = await axios.get(`http://localhost:3000/getReport?id=${idBorrador}`); // 更新状态而非操作DOM setTipo(response.data.tipo); setNota(response.data.nota); } catch (error) { console.error('Error fetching data for the draft:', error); } }; fetchData(); } }, []); // 当nota数据更新且编辑器已初始化完成时,设置编辑器内容 useEffect(() => { if (editorRef.current && nota) { editorRef.current.setData(nota); } }, [nota]); return ( <div> {/* 用状态绑定输入框,而非直接操作DOM */} <input id="tipo" value={tipo} onChange={(e) => setTipo(e.target.value)} /> <CKEditor editor={ClassicEditor} id="cuerpo" name="cuerpo" onReady={(editor) => { // 保存编辑器实例到ref editorRef.current = editor; // 若初始加载时已有数据,直接设置 if (nota) { editor.setData(nota); } }} /> </div> ); } export default ReportEditor;
替代方案:直接通过data属性绑定状态
如果不需要手动调用编辑器API,也可以直接将状态绑定到CKEditor的data属性,React会自动在状态变化时更新编辑器内容:
<CKEditor editor={ClassicEditor} id="cuerpo" name="cuerpo" data={nota} // 直接绑定状态 onReady={(editor) => { editorRef.current = editor; }} />
为什么你的原有方法无效?
- 'editor not defined'错误:你没有保存CKEditor的实例引用,空依赖的
useEffect执行时编辑器可能还未初始化,且无法访问到编辑器实例 - 直接用DOM值赋值
data属性:组件首次渲染时接口请求还未完成,aux输入框的值是空的;后续数据更新后,由于没有状态触发组件重新渲染,CKEditor不会读取新的DOM值
内容的提问来源于stack exchange,提问作者Ignacio Puppo
相关产品推荐
相关产品推荐

