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

使用Liveblocks创建房间时遭遇TypeError错误求助

使用Liveblocks创建房间时出现TypeError: (0 , liveblocks_react__WEBPACK_IMPORTED_MODULE_1_.default) 不是一个函数

错误详情

服务器错误
TypeError: (0 , liveblocks_react__WEBPACK_IMPORTED_MODULE_1_.default) 不是一个函数
该错误在页面生成时发生,控制台日志将显示在终端窗口。
来源
liveblocks.config.ts (85:78) @ client

83 | useRemoveReaction,
84 | }
85 | } = createRoomContext<Presence, Storage, UserMeta, RoomEvent, ThreadMetadata>(client, {
| ^
86 | async resolveUsers({ userIds }) {
87 | // 仅用于评论功能。返回从userIds获取的用户信息列表,该信息用于评论、提及等场景。
88 | // 从userIds获取用户信息

相关代码

room.tsx

import  {ReactNode} from 'react';
import  {ClientSideSuspense} from '@liveblocks/react'

import  {RoomProvider}  from '@/liveblocks.config';

interface RoomProps { 
  children: ReactNode
  roomId: string;
  fallback: NonNullable<ReactNode> | null;
};
const Room = ({ 
  children,
  roomId,
  fallback,
}: RoomProps) => {
  return (
    <RoomProvider 
    id={roomId} 
    initialPresence={
      {}
    }
    // initialStorage={{
    //   layers: new LiveMap<string, LiveObject<Layer>>(),
    //   layerIds: new LiveList(),
    // }}
  >
    <ClientSideSuspense fallback={fallback}>
      {() => children}
    </ClientSideSuspense>
  </RoomProvider>
    )
}


export default Room

page.tsx

import React from 'react'
import Canvas from  './_components/canvas'
import Room from '@/components/room';
import SimpleLoader from '@/components/Loaders/simple-loader';

interface BoardIdPageProps {
    params: {
      boardId: string;
    };
  };
  
  const BoardIdPage = ({
    params,
  }: BoardIdPageProps) => {  
  return (
    <main
      className="h-full w-full relative bg-neutral-100 touch-none"
    >
      <Room roomId={params.boardId} fallback={<SimpleLoader />}> 
        <Canvas boardId={params.boardId} />
      </Room>
        
    </main>
  )
}

export default BoardIdPage

liveblocks.config.ts

import { createClient } from "@liveblocks/client";
import { createRoomContext } from "@liveblocks/react";
  
const client = createClient({
  publicApiKey: "pk_dev_Mlm5l54BhELjDRrhRrvlbBAih9GS5wCPSTLaXLeBXZpiDI7Cw_BCNyURhNuTEtvt",  
});

// Presence代表房间内每个用户都存在且会自动同步的属性,可通过`user.presence`访问,必须可JSON序列化。
type Presence = {
  // cursor: { x: number, y: number } | null,
  // ...
};

// 可选:Storage代表房间内持久化的共享文档,即使所有用户离开也会保留。Storage下的字段通常是LiveList、LiveMap、LiveObject实例,其更新会自动持久化并同步到所有连接的客户端。
type Storage = {
  // author: LiveObject<{ firstName: string, lastName: string }>,
  // ...
};

// 可选:UserMeta代表每个用户的静态/只读元数据,由自定义认证后端提供(若使用),适用于会话期间不会更改的数据,如用户名或头像。
type UserMeta = {
  // id?: string,  // 可通过`user.id`访问
  // info?: Json,  // 可通过`user.info`访问
};

// 可选:本房间内广播和监听的自定义事件类型,使用联合类型表示多个事件,必须可JSON序列化。
type RoomEvent = {
  // type: "NOTIFICATION",
  // ...
};

// 可选:使用评论功能时,ThreadMetadata代表每个线程的元数据,仅可包含布尔值、字符串和数字。
export type ThreadMetadata = {
  // resolved: boolean;
  // quote: string;
  // time: number;
};

export const {
  suspense: {
    RoomProvider,
    useRoom,
    useMyPresence,
    useUpdateMyPresence,
    useSelf,
    useOthers,
    useOthersMapped,
    useOthersConnectionIds,
    useOther,
    useBroadcastEvent,
    useEventListener,
    useErrorListener,
    useStorage,
    useObject,
    useMap,
    useList,
    useBatch,
    useHistory,
    useUndo,
    useRedo,
    useCanUndo,
    useCanRedo,
    useMutation,
    useStatus,
    useLostConnectionListener,
    useThreads,
    useUser,
    useCreateThread,
    useEditThreadMetadata,
    useCreateComment,
    useEditComment,
    useDeleteComment,
    useAddReaction,
    useRemoveReaction,
  }
} = createRoomContext<Presence, Storage, UserMeta, RoomEvent, ThreadMetadata>(client, {
  async resolveUsers({ userIds }) {
    // 仅用于评论功能。返回从`userIds`获取的用户信息列表,该信息用于评论、提及等场景。
    
    // const usersData = await __fetchUsersFromDB__(userIds);
    // 
    // return usersData.map((userData) => ({
    //   name: userData.name,
    //   avatar: userData.avatar.src,
    // }));
    
    return [];
  },
  async resolveMentionSuggestions({ text, roomId }) {
    // 仅用于评论功能。返回匹配`text`的用户ID列表,这些ID用于在编辑器中输入时创建提及列表。
    //
    // 例如当输入"@jo"时,`text`为"jo",应返回John和Joanna的用户ID数组:
    // ["john@example.com", "joanna@example.com"]
    
    // const userIds = await __fetchAllUserIdsFromDB__(roomId);
    //
    // 若没有`text`则返回所有用户ID
    // if (!text) {
    //   return userIds;
    // }
    //
    // 否则根据搜索文本过滤用户ID并返回
    // return userIds.filter((userId) => 
    //   userId.toLowerCase().includes(text.toLowerCase())  
    // );
    
    return [];
  },
});
解决方案

这个错误的核心是Liveblocks版本不兼容或API导入/调用方式错误,以下是具体修复步骤:

  • 统一依赖版本
    确保@liveblocks/client和@liveblocks/react版本完全一致,版本不匹配会导致API冲突。执行命令更新到最新版:

    npm install @liveblocks/client@latest @liveblocks/react@latest
    # 或使用yarn
    yarn add @liveblocks/client@latest @liveblocks/react@latest
    
  • 修正createRoomContext的导入与调用
    如果你使用的是Liveblocks v1.x及以上版本,Suspense模式的API已调整,需要从专门的路径导入:

    // 替换原导入语句
    import { createRoomContext } from "@liveblocks/react/suspense";
    

    同时,返回的RoomProvider及hooks无需从suspense属性中解构,直接获取即可:

    export const {
      RoomProvider,
      useRoom,
      useMyPresence,
      // ... 其他需要的hooks
    } = createRoomContext<Presence, Storage, UserMeta, RoomEvent, ThreadMetadata>(client, {
      // 配置项保持不变
    });
    
  • 验证RoomProvider使用
    确保room.tsx中导入的RoomProvider来自修正后的liveblocks.config.ts,且id属性正确传入roomId,这部分你的代码已符合要求,无需额外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:25:56