react-wysiwyg点击textarea空白页 getBlockMap报错
问题根因
报错Uncaught TypeError: contentState.getBlockMap is not a function的核心原因是传入Draft API的参数不是合法的ContentState实例,是普通JS对象/格式错误的数据,代码里一共有4个明确问题:
convertFromHTML返回值直接传给EditorState.createWithContent的写法错误:原生Draft.js的convertFromHTML返回结构是{contentBlocks, entityMap},不能直接作为ContentState使用;只有draft-convert库的同名方法才会直接返回ContentState实例。- 数据格式混用:你在
respChange里把convertToRaw(state.getCurrentContent())(普通JSON对象,不是ContentState)存到了上层状态,下次组件渲染时直接把这个raw格式对象传给convertFromHTML,转换出来的结果完全不符合ContentState结构,编辑器触发更新时就会抛出找不到getBlockMap方法的错误。 - 组件参数解构有语法错误:
const TabContent = ({ onChange, resp, , status })里resp后面多了一个多余逗号,会导致props解构异常,拿到的resp值不符合预期。 - DOM属性名书写错误:
wrapperclassName、editorclassName没有按React驼峰规范书写,正确属性名是wrapperClassName、editorClassName,写错会导致样式不生效。
修复方案
按以下规则调整代码即可:
- 统一数据格式:上层状态、组件间传递的resp/name字段统一存RawDraftContent格式(就是
convertToRaw返回的JSON结构),只有在提交接口、渲染纯HTML的时候再做格式转换,避免字符串、Raw对象、ContentState实例混传。 - 初始化编辑器时先判断传入值的类型,对应做格式转换,不合法值直接返回空编辑器状态。
- 修正语法错误,补全未闭合的标签、缺失的属性绑定。
修复后的核心代码
// 按你用的工具库正确导入方法,以下是常用搭配示例 import { EditorState, convertFromRaw, convertToRaw } from 'draft-js'; import { Editor } from 'react-draft-wysiwyg'; import { convertToHTML, convertFromHTML } from 'draft-convert'; import { useState } from 'react'; const TabContent = ({ onChange, resp, name, status }) => { // 统一封装编辑器初始化逻辑 const initEditorState = (content) => { if (!content) return EditorState.createEmpty(); // 处理RawDraft格式的存值 if (typeof content === 'object' && content.blocks) { return EditorState.createWithContent(convertFromRaw(content)); } // 处理HTML字符串格式的初始值 if (typeof content === 'string') { return EditorState.createWithContent(convertFromHTML(content)); } return EditorState.createEmpty(); }; // resp编辑器状态 const [respEditor, setRespEditor] = useState(() => initEditorState(resp)); // name编辑器逻辑和resp完全一致,照着实现即可 const [nameEditor, setNameEditor] = useState(() => initEditorState(name)); function respChange(state) { setRespEditor(state); onChange({ resp: convertToRaw(state.getCurrentContent()), name, status }); } // name编辑器change事件照着respChange写即可 function nameChange(state) { setNameEditor(state); onChange({ resp: convertToRaw(respEditor.getCurrentContent()), name: convertToRaw(state.getCurrentContent()), status }); } const handle = async (e) => { e.preventDefault(); try { await fetch("", { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ // 提交时再转成HTML字符串 resp: convertToHTML(respEditor.getCurrentContent()), name: convertToHTML(nameEditor.getCurrentContent()), status }) }); } catch (err) { console.log(err); } }; return ( <form onSubmit={handle}> <Editor editorState={respEditor} onEditorStateChange={respChange} wrapperClassName="wrapperclassName" editorClassName="editorclassName" toolbar={{ options: ["inline"], inline: { inDropdown: false } }} /> {/* name编辑器照着resp编辑器放即可 */} <Editor editorState={nameEditor} onEditorStateChange={nameChange} wrapperClassName="wrapperclassName" editorClassName="editorclassName" /> <input type="radio" value="B" checked={status === "B"} onChange={(e) => onChange({ resp: convertToRaw(respEditor.getCurrentContent()), name: convertToRaw(nameEditor.getCurrentContent()), status: e.target.value }) } /> <button type="submit">提交</button> </form> ); };
如果你没有用
draft-convert库,用的是Draft.js原生自带的convertFromHTML,初始化HTML内容的逻辑要替换成下面的写法:import { ContentState } from 'draft-js'; const { contentBlocks, entityMap } = convertFromHTML(content); const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap); return EditorState.createWithContent(contentState);
内容的提问来源于stack exchange,提问作者Zokulko
相关产品推荐
相关产品推荐

