从Firebase加载数据后无法编辑Draft.js编辑器文本
问题分析与修复方案
核心问题:编辑器状态被频繁重置
你的Editor组件每次渲染时都会通过EditorState.createWithContent(ContentState.createFromText(text))创建全新的编辑器状态,这会导致用户输入时,组件重渲染就会覆盖当前编辑状态,直接表现为光标固定、无法编辑。
修复步骤
1. 正确初始化和绑定编辑器状态
把编辑器状态的初始化与更新逻辑从组件props中剥离,放到useEffect中处理:
// 原编辑器状态初始化保留 const [editorState, setEditorState] = useState(() => EditorState.createEmpty()); // 当从数据库获取到文本内容时,更新编辑器状态 useEffect(() => { if (text) { const contentState = ContentState.createFromText(text); setEditorState(EditorState.createWithContent(contentState)); } }, [text]);
然后修改Editor组件的props,直接绑定已有的状态:
<Editor editorState={editorState} onEditorStateChange={setEditorState} wrapperClassName="wrapper-class" editorClassName="editor-class" toolbarClassName="toolbar-class" />
2. 修复文章获取的无限循环问题
获取文章的useEffect依赖中包含post,会导致每次post更新时重复触发请求,形成无限循环,移除该依赖:
useEffect(() => { const getPost = async () => { const docRef = doc(db, 'posts', id); try { const docSnap = await getDoc(docRef); const postData = docSnap.data(); setPost(postData); const text = htmlToText(postData.body, {}); setText(text); } catch (error) { console.log(error) } }; getPost(); }, [id]); // 仅保留id作为依赖
3. 同步编辑器内容到表单数据
原转换HTML的useEffect依赖为空数组,无法随编辑器状态更新同步表单数据,修改依赖并优化更新逻辑:
useEffect(() => { const html = convertToHTML(editorState.getCurrentContent()); setConvertedContent(html); setFormData(prev => ({ ...prev, body: html })); }, [editorState]); // 依赖改为editorState,随编辑器状态更新触发
4. 优化图片URL同步逻辑
移除不必要的依赖,避免无效触发:
useEffect(() => { if (imageURL) { setFormData(prev => ({ ...prev, image: imageURL })); } }, [imageURL]); // 仅保留imageURL作为依赖
额外建议:保留原文章格式
目前你把HTML转成纯文本再导入编辑器,会丢失原有的格式。可以使用draft-js-import-html库直接将HTML转换为Draft.js的ContentState,保留原文章格式:
- 安装依赖:
npm install draft-js-import-html - 修改文章获取逻辑:
import { stateFromHTML } from 'draft-js-import-html'; // 在getPost函数中替换htmlToText部分 const contentState = stateFromHTML(postData.body); setEditorState(EditorState.createWithContent(contentState)); // 可删除text相关的useState及处理逻辑
内容的提问来源于stack exchange,提问作者Julian
相关产品推荐
相关产品推荐

