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

如何在MongoDB持久化Y.js的yDoc并复用?解决doc.on()报错

解决TipTap协作扩展YDoc持久化到MongoDB后的doc.on()不存在错误

错误核心原因

出现TypeError: doc.on() does not exist的本质是恢复后的YDoc实例异常,通常由以下两种情况导致:

  1. MongoDB存储/读取Uint8Array时的类型转换错误,导致Y.applyUpdate无法正确解析状态,损坏YDoc实例。
  2. YDoc初始化方式或版本兼容性问题,导致创建的实例不符合TipTap协作扩展的要求。

具体解决方案

1. 修正MongoDB的二进制数据处理逻辑

MongoDB对Uint8Array的存储需要保持二进制类型,避免转成普通数组或字符串:

  • 存储时:直接将Y.encodeStateAsUpdate(yDoc)返回的Uint8Array存入,MongoDB会自动将其转为BinData(0)类型,无需额外处理:
    const update = Y.encodeStateAsUpdate(yDoc);
    await db.collection('docs').updateOne(
      { _id: docId },
      { $set: { state: update } },
      { upsert: true }
    );
    
  • 读取时:将MongoDB返回的BinData转换回Uint8Array,不能直接使用原始返回值:
    const storedDoc = await db.collection('docs').findOne({ _id: docId });
    // 若使用Mongoose,需通过.buffer获取二进制数据
    const updateUint8 = new Uint8Array(storedDoc.state.buffer);
    

2. 规范YDoc的初始化与状态恢复流程

  • 优先使用TipTap提供的createYDoc方法创建实例(确保与协作扩展兼容),而非直接new Y.Doc():
    import { createYDoc } from '@tiptap/core';
    import * as Y from 'yjs';
    
    const newDoc = createYDoc();
    Y.applyUpdate(newDoc, updateUint8);
    
  • 若必须使用new Y.Doc(),需确保yjs版本与@tiptap/extension-collaboration依赖的版本完全一致(版本不匹配会导致实例方法缺失)。

3. 适配Next.js 14客户端组件的执行时机

在客户端组件中,需将YDoc的恢复逻辑放在useEffect中执行,避免SSR hydration阶段的异常:

'use client';

import { useEffect, useState } from 'react';
import { EditorProvider } from '@tiptap/react';
import { Collaboration } from '@tiptap/extension-collaboration';
import { createYDoc } from '@tiptap/core';
import * as Y from 'yjs';

export default function Editor({ docId }) {
  const [yDoc, setYDoc] = useState(null);

  useEffect(() => {
    const restoreDoc = async () => {
      // 从API获取存储的状态
      const res = await fetch(`/api/docs/${docId}`);
      const data = await res.json();
      // 转换为Uint8Array
      const update = new Uint8Array(Object.values(data.state));
      // 创建并恢复YDoc
      const doc = createYDoc();
      Y.applyUpdate(doc, update);
      setYDoc(doc);
    };

    restoreDoc();
  }, [docId]);

  if (!yDoc) return <div>加载中...</div>;

  return (
    <EditorProvider yDoc={yDoc} extensions={[Collaboration]}>
      {/* 编辑器内容 */}
    </EditorProvider>
  );
}

4. 验证版本兼容性

执行以下命令确保所有依赖版本匹配:

npm install yjs@latest @tiptap/core@latest @tiptap/extension-collaboration@latest

内容的提问来源于stack exchange,提问作者Raumil Dhandhukia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:37:17