You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Draft-JS编辑器从服务端加载内容后仅显示原生Emoji问题求助

Draft-JS 仅显示原生Emoji问题排查与解决办法

问题描述

我碰到了一个Draft-JS的奇怪问题:当我从服务端获取contentState数据,通过convertFromRaw转换后传入编辑器,里面的Emoji只能显示系统原生样式;但在把内容发送到服务端之前,聊天编辑器里的Emoji显示完全正常。

相关代码如下:

流程代码

const contentState = convertFromRaw(JSON.parse(comment.message))
const editorState = EditorState.createWithContent(contentState)
<ChatTemplate 
  user={currentUser === comment.userId} 
  value={editorState} 
  time={moment(comment.createdAt).startOf('second').fromNow()} 
/>

编辑器组件代码

const ChatTemplate = (p)=>(
  <div className='globalMassage-cont' data-user={p.user} >
    <div className='globalMassage-value'>
      <Editor editorState={p.value} plugins={plugins} readOnly />
    </div>
  </div>
)

导入与常量定义

import Editor, { createEditorStateWithText } from "draft-js-plugins-editor";
import createEmojiPlugin from "draft-js-emoji-plugin";
import { EditorState, ContentState, convertFromRaw } from "draft-js";

const emojiPlugin = createEmojiPlugin();
const { EmojiSuggestions, EmojiSelect } = emojiPlugin;
const plugins = [emojiPlugin];

原因分析

这个问题的核心在于draft-js-emoji-plugin的渲染逻辑没有参与到EditorState的初始化过程:

  • 当你在编辑器里插入插件提供的Emoji时,插件会给对应的内容块添加专属的entity元数据,用来标记这是需要插件自定义渲染的Emoji。
  • 但convertFromRaw是Draft-JS核心的转换方法,它只会处理基础的ContentState结构,不会触发插件的解析逻辑。所以当你直接用它创建EditorState时,插件无法识别那些带专属标记的Emoji,只能 fallback 到系统原生Emoji显示。

解决办法

这里有两种靠谱的解决思路,你可以根据自己的场景选择:

方法一:初始化EditorState时传入插件的Decorator

draft-js-emoji-plugin提供了专属的decorator,用来处理Emoji的渲染逻辑。你只需要在创建EditorState时把它传进去,插件就能在初始化阶段识别并处理Emoji内容:

修改你的流程代码:

// 先解析服务端返回的原始数据
const rawContent = JSON.parse(comment.message);
const contentState = convertFromRaw(rawContent);

// 关键:传入emojiPlugin的decorator,让插件参与初始化
const editorState = EditorState.createWithContent(
  contentState,
  emojiPlugin.decorator
);

<ChatTemplate 
  user={currentUser === comment.userId} 
  value={editorState} 
  time={moment(comment.createdAt).startOf('second').fromNow()} 
/>

方法二:确保服务端存储完整的插件处理数据

如果方法一没生效,你需要检查发送到服务端的数据是否完整。在发送内容前,必须用convertToRaw导出包含插件元数据的完整ContentState:

示例发送代码:

// 获取当前编辑器的完整ContentState
const currentContent = editorState.getCurrentContent();
// 转换为原始JSON结构(包含插件添加的Emoji元数据)
const rawContent = convertToRaw(currentContent);

// 发送到服务端(注意转成JSON字符串)
fetch('/api/save-comment', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ 
    message: JSON.stringify(rawContent) 
  })
});

确保服务端存储的是这个完整的rawContent,而不是被截断或修改过的数据。这样当你从服务端取回数据转换时,插件就能正确识别Emoji标记。


验证步骤

修改后重新测试:

  1. 发送一条带插件Emoji的消息到服务端
  2. 刷新页面,从服务端取回这条消息
  3. 检查编辑器里的Emoji是否显示为插件样式,而非原生样式

内容的提问来源于stack exchange,提问作者elad BA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:39:15