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

如何将Draft.js富文本内容携带样式发送至MongoDB存储

富文本内容存取MongoDB实现方案

核心问题定位

  • 现有TextEditor组件未将富文本内容透传给父组件,父组件绑定的onChange是原生输入框的取值逻辑,无法获取富文本的格式化内容
  • 序列化/反序列化方法调用位置错误:convertToRaw要在编辑器内容更新、提交给后端前调用,convertFromRaw要在从后端拿到存储内容、回显渲染时调用
  • 现有Mongoose模型无需修改,String类型完全支持存储序列化后的富文本内容

分步修改代码

1. 修改TextEditor组件,向外同步编辑内容

在编辑器状态更新的回调里,除了更新组件自身state,同时把序列化后的内容通过props传递给父组件。

两种存储模式二选一即可:

  • 模式1:存储Draft.js原生Raw JSON:无损保留所有编辑状态,后续支持二次编辑富文本
  • 模式2:存储转换后的HTML字符串:存储后直接渲染即可,不需要二次转换,适合仅展示场景
    修改后的TextEditor.js代码:
import React, { Component } from "react";
import { Editor } from "react-draft-wysiwyg";
import { EditorState, convertToRaw } from "draft-js";

import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import draftToHtml from "draftjs-to-html";

export default class TextEditor extends Component {
  state = {
    editorState: EditorState.createEmpty(),
  };

  onEditorStateChange = (editorState) => {
    this.setState({
      editorState,
    });
    // 内容变化时同步给父组件
    const contentState = editorState.getCurrentContent();
    // --- 模式1:存Raw JSON 用下面这行---
    const contentValue = JSON.stringify(convertToRaw(contentState));
    // --- 模式2:存HTML 用下面这行,二选一---
    // const contentValue = draftToHtml(convertToRaw(contentState));
    
    // 调用父组件传入的onChange回传内容
    this.props.onChange(contentValue);
  };

  render() {
    const { editorState } = this.state;
    return (
      <div>
        <Editor
          editorState={editorState}
          toolbarClassName="toolbarClassName"
          wrapperClassName="wrapperClassName"
          editorClassName="editorClassName"
          onEditorStateChange={this.onEditorStateChange}
          placeholder={this.props.placeholder}
        />
        {/* 不需要预览可以删掉下面的textarea */}
        <textarea
          disabled
          value={draftToHtml(convertToRaw(editorState.getCurrentContent()))}
        ></textarea>
      </div>
    );
  }
}

2. 修改Write.jsx页面,正确接收富文本内容提交

TextEditor不是原生表单元素,不会返回标准event对象,直接接收子组件回传的内容赋值即可。
修改后的Write.jsx代码:

import { useState, useContext } from 'react';
import axios from 'axios';
import TextEditor from '../../components/TextEditor/TextEditor';
import { Context } from '../../context/Context'; // 替换为你项目的Context实际引入路径

export default function Write() {
  const [desc, setDesc] = useState('');
  const { user } = useContext(Context);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const newPost = {
      username: user.username,
      desc, // 这里拿到的就是序列化好的富文本内容,直接提交即可
    };
    try {
      const res = await axios.post('/posts', newPost);
      window.location.replace('/post/' + res.data._id);
    } catch (err) {
      console.log(err);
    }
  };

  return (
    <div className='write'>
      <form className='writeForm' onSubmit={handleSubmit}>
        <TextEditor
          placeholder='Write your story'
          className='writeInput writeText'
          // 直接接收子组件回传的内容,不需要e.target.value
          onChange={(value) => setDesc(value)}
        />

        <button className='writeSubmit' type='submit'>
          نشر
        </button>
      </form>
    </div>
  );
}

注意:原代码缺少useState、useContext的引入,Context的引入路径需要替换为项目实际路径,否则会运行报错。

3. 读取内容渲染(详情页使用)

根据之前选择的存储模式,对应渲染即可:

  • 如果选的模式2(存HTML):直接把从接口拿到的desc字段渲染到页面即可,示例:
    <div className="postContent" dangerouslySetInnerHTML={{__html: post.desc}}></div>
    
  • 如果选的模式1(存Raw JSON):需要先反序列化再转换,既支持回显到富文本编辑器二次编辑,也可以转成HTML渲染:
    import { convertFromRaw, EditorState } from 'draft-js';
    import draftToHtml from 'draftjs-to-html';
    
    // 接口拿到desc后处理
    const rawContent = JSON.parse(post.desc);
    const contentState = convertFromRaw(rawContent);
    // 转HTML直接渲染
    const htmlContent = draftToHtml(rawContent);
    // 回显到编辑器做二次编辑用
    const editorState = EditorState.createWithContent(contentState);
    

补充说明

现有Post.js Mongoose模型不需要修改,desc字段设为String类型可以正常存储两种格式的富文本内容,不会出现样式丢失问题。

内容的提问来源于stack exchange,提问作者sultan.h

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:48:28