@colyseus/react

中文文档
0.18.4发布于 2026/10/03TypeScriptESM + CJS零依赖近 30 天下载 2731

反应钩 科利赛 多人应用.

中文使用文档
文档目录22 节
  1. 安装
  2. 服务器侧渲染
  3. 钩子
  4. useRoom(callback, deps?)
  5. useRoomState(room, selector?)
  6. useRoomMessage(room, type, callback)
  7. useLobbyRoom(callback, deps?)
  8. useQueueRoom(connect, consume, deps?)
  9. 网码钩 (Colyseus 0.18+)
  10. usePredict(room, options?)
  11. useInput(room, options?)
  12. usePredictLoop(room, onSteps, options?)
  13. useReconciler(room, select, options)
  14. useAttachAll(room, key, config, deps?)
  15. useEventChannel(room, options)
  16. useEntityInstance(room, select) 编号 : useSessionEntity(room,…
  17. getSchemaInstance(snapshot)
  18. useInputBuffer()
  19. 背景情况
  20. createRoomContext()
  21. createLobbyContext()
  22. 贷项

@colyseus/ 反应

反应钩 科利赛 多人应用.

安装

npm install @colyseus/react

同伴依赖性 : @colyseus/sdk, (中文(简体) ), @colyseus/schema,以及 react (单位:千美元).

服务器侧渲染

每个钩子在服务器上都是安全的 一个房间是现场客户端 连接并且从未被串行用于水合, 所以在服务器上的钩子 仿佛无所事事 useRoomState() 返回时 undefined, (中文(简体) ), useRoom() 报告 isConnecting: true,预测钩子返回 undefined连接在某种效果中发生,所以客厅到达 水分补充后立即恢复.

创建连接状态而不是假设状态:

const players = useRoomState((state) => state.players);
if (!players) return <Spinner />;   // server render + first client paint

货包船a "use client" 指令,这样您就可以从一个 Next.js App 路由器服务器组件没有构建失败 。 钩子 就像任何反应钩一样.

钩子

useRoom(callback, deps?)

管理Colyseus房间连接的生命周期。 处理连接,断开挂载, 当依赖关系改变时重新连接 。 正确使用 React PrintMode .

import { Client } from "@colyseus/sdk";
import { useRoom } from "@colyseus/react";

const client = new Client("ws://localhost:2567");

function Game() {
  const { room, error, isConnecting } = useRoom(
    () => client.joinOrCreate("game_room"),
  );

  if (isConnecting) return <p>Connecting...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return <GameView room={room} />;
}

第一个参数是返回 a 的回调 Promise<Room> - 任何Colyseus配对方法都有效(joinOrCreate, (中文(简体) ), join, (中文(简体) ), create, (中文(简体) ), joinById, (中文(简体) ), consumeSeatReservation) (中文(简体) ).

根据依赖性变化重新连接 :

const { room } = useRoom(
  () => client.joinOrCreate("game_room", { level }),
  [level],
);

何时 level 更改前一个房间左边,并建立新的连接.

有条件连接 :

传递 falsy 值以跳过连接直到满足条件 :

const { room } = useRoom(
  isReady ? () => client.joinOrCreate("game_room") : null,
  [isReady],
);

useRoomState(room, selector?)

订阅 Colyseus 房间状态变化并返回不可改变的平面对象快照 。 状态树的未更改部分保留了commerds之间的偏好等同,所以当它们实际使用的数据被改变时,只重新激活组件.

import { useRoom, useRoomState } from "@colyseus/react";

function Game() {
  const { room } = useRoom(() => client.joinOrCreate("game_room"));
  const state = useRoomState(room);

  if (!state) return <p>Waiting for state...</p>;

  return <p>Players: {state.players.size}</p>;
}

使用选择器 以订阅状态的子集 :

const players = useRoomState(room, (state) => state.players);

仅读取组件 players 当玩家地图改变时, 将会重新回复.

useRoomMessage(room, type, callback)

订阅 Colyseus 房间信息。 召回器保存在回放器中,所以它总是更新而无需重新订阅. 当房间改变或组件卸载时自动取消订阅.

import { useRoom, useRoomMessage } from "@colyseus/react";

function Chat() {
  const { room } = useRoom(() => client.joinOrCreate("game_room"));
  const [messages, setMessages] = useState<string[]>([]);

  useRoomMessage(room, "chat", (message) => {
    setMessages((prev) => [...prev, message]);
  });

  return (
    <ul>
      {messages.map((msg, i) => <li key={i}>{msg}</li>)}
    </ul>
  );
}

过 "*" 作为所有消息类型的监听类型.

useLobbyRoom(callback, deps?)

连接到 Colyseus 大厅 并提供了可用房间的现场更新清单。 随着房间的创建、更新和去除,清单将自动保持.

import { Client } from "@colyseus/sdk";
import { useLobbyRoom } from "@colyseus/react";

const client = new Client("ws://localhost:2567");

function Lobby() {
  const { rooms, error, isConnecting } = useLobbyRoom(
    () => client.joinOrCreate("lobby"),
  );

  if (isConnecting) return <p>Connecting...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <ul>
      {rooms.map((room) => (
        <li key={room.roomId}>
          {room.name} — {room.clients}/{room.maxClients} players
        </li>
      ))}
    </ul>
  );
}

返回值:

外地类型说明
roomsRoomAvailable<Metadata>[]可用房间实况列表
roomRoom | undefined地下大厅连接
errorError | undefined连接出错( 如果有)
isConnectingbooleantrue 在连接大厅时

useQueueRoom(connect, consume, deps?)

管理一个 Colyseus 匹配队列的整个生命周期:连接到排队室,跟踪组大小,接收座位预定,确认,并消耗座位加入匹配室. 把两个房间都清理干净.

import { Client } from "@colyseus/sdk";
import { useQueueRoom } from "@colyseus/react";

const client = new Client("ws://localhost:2567");

function Matchmaking() {
  const { room, clients, isWaiting, error } = useQueueRoom(
    () => client.joinOrCreate("queue", { rank: 1200 }),
    (reservation) => client.consumeSeatReservation(reservation),
  );

  if (error) return <p>Error: {error.message}</p>;
  if (room) return <GameScreen room={room} />;
  if (isWaiting) return <p>Waiting for match... {clients} players in group</p>;
  return <p>Connecting...</p>;
}

第一个参数连接到队列室. 第二个论点是: SeatReservation 一旦找到匹配点——使用 client.consumeSeatReservation() 加入比赛室.

返回值:

外地类型说明
roomRoom | undefined火柴房,一旦座椅被消耗
queueRoom | undefined等待时的队列室( 匹配后未定义)
clientsnumber当前配对组中的客户数
seatSeatReservation | undefined座位预定,一旦收到
errorError | undefined连接或匹配出错
isWaitingbooleantrue 连接到队列并等待匹配时

网码钩 (Colyseus 0.18+)

反应约束 @colyseus/sdk 预测工具——客户预测,调节和远程平滑. 见 网码文件 对于基本的概念.

一条规则是: 结构通过快照实现,运动通过预测读取实现. useRoomState 以补丁速率重交 原始同步值 - 从它做位置 让你焦躁的补丁率运动。 预测值/模拟值改变每个框架,必须远离反应渲染周期:用 predict.value(instance, field) 在您的帧环( R3F) useFrame,或 usePredictLoop 并写入参考文献.

下面所有钩子都以两种形式存在: 独立(useX(room, ...))和被捆绑(由 createRoomContext(options),没有房间争论). 将预测选项通过一次 createRoomContext({ predict: { mode: "lerp", delay: 100 } })。 。 。 .

usePredict(room, options?)

返回共享的房间 Predict 举个例子. Predict.get() 每个呼叫构造一个新实例,所以钩子会记住每个房间一个,参考点数消费者,当最后的消费者卸载时处理.

useInput(room, options?)

回到房间 InputHandle (单位:千美元)room.input() ——一能,每室稳定. 阶段字段开始 input.data,则 input.send() 每一固定步骤 usePredictLoop 调用.

usePredictLoop(room, onSteps, options?)

拥有每帧驱动程序: 呼叫 predict.tick(now) 每帧一次,然后将到期的固定步骤数交给您——相位+准确发送回调内的许多输入("读取前发送"). 默认它会自己运行 requestAnimationFrame; 与 { external: true } 它返回一个 drive(now?) 函数从您已有的框架循环调用 :

// React Three Fiber — drive at an early priority so ticks precede reads:
const drive = usePredictLoop(onSteps, { external: true });
useFrame(() => drive(), -1);

useReconciler(room, select, options)

积极预测你控制的实体—— predict.reconciler() 处理的生命周期:等待实体产出(select: (state, room) => instance),如果服务器替换实例,则重新创建控制器,并在卸载上处理. options.input 默认为房间的把手.

const me = useReconciler(
  (state, room) => state.players.get(room.sessionId),
  { step: (ctx, p, cmd) => applyInput(p, cmd, ctx.dt), smoothing: 15, snap: 5 },
);

useAttachAll(room, key, config, deps?)

被动平滑为根态收藏—— predict.attachAll() 作为一种效果,脱去在卸载上。 在单独的调用中附加角字段 :

useAttachAll("players", { mode: "lerp", fields: ["x", "y", "z"] });
useAttachAll("players", { mode: "lerp", fields: ["heading"], angle: true });

useEventChannel(room, options)

乐观事件频道—— predict.defineEvent() 以倾覆而未登起者发誓, 加反应:调用组件在预测/确认/弹出/未预测上重新调用,所以旗形的引出工作以平面渲染码:

const pickups = useEventChannel({
  confirmOn: { collection: "items", field: "alive", equals: false },
});
const hidden = !item.alive || pickups?.has(id);

useEntityInstance(room, select) 编号 : useSessionEntity(room, collectionKey)

选择一个 已解码的计划实例 (Prectt APIs 键关闭),只有当其身份变化时才会重新发回——从不在字段更新上发回. useSessionEntity 常见情况: 由 sessionId。 。 。 .

getSchemaInstance(snapshot)

桥梁 useRoomState 将快照折回解码实例中 predict.value() 阅读您从快照列表中获取的实体:

const source = getSchemaInstance(playerSnapshot);
useFrame(() => { ref.current.position.x = predict.value(source, "x"); });

useInputBuffer()

这个 "缓冲,然后消耗" 作为钩子的输入食谱 : press() 在事件处理器中, consume() 在发送回路中,一个水龙头在精确的固定步骤上降落——在0步框架上从未丢失,在多步框架上从未加倍.

完整的实例(R3F + 预测 + 远程麻黄),见 r3f-lobby-car-原型。 。 。 .

背景情况

createRoomContext()

创建一组钩子和一个 RoomProvider 组件,共享一个跨React调和器边界的单室连接(如DOM + React Three Fiber). 房间被储存在一个封闭的外置商店,而不是反应上下文,因此钩子在任何导入它们的调和树上工作.

import { Client } from "@colyseus/sdk";
import { createRoomContext } from "@colyseus/react";

const client = new Client("ws://localhost:2567");

const { RoomProvider, useRoom, useRoomState } = createRoomContext();

包装您的应用程序 RoomProvider数字 :

function App() {
  return (
    <RoomProvider connect={() => client.joinOrCreate("game_room")}>
      <UI />
      <Canvas>
        <GameScene />
      </Canvas>
    </RoomProvider>
  );
}

RoomProvider 接受一个 connect 调用( 与独立 useRoom 钩子)和可选 deps 阵列。 传递一个 falsy 值到 connect 推迟连接.

使用任意组件中的钩子——DOM或R3F:

function UI() {
  const { room, error, isConnecting } = useRoom();
  const players = useRoomState((state) => state.players);

  if (isConnecting) return <p>Connecting...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return <p>Players: {players?.size}</p>;
}

回来的 useRoom() 财务报告和审定财务报表 useRoomState(selector?) 工作与独立的钩子相同,但不要要求你通过房间作为辩论.

createLobbyContext()

创建一个 LobbyProvider 财务报告和审定财务报表 useLobby 在您的应用软件上分享大厅室数据的钩子——当您需要房间元数据时, 不仅在大厅屏幕上, 喜欢 createRoomContext,它使用一个闭合镜外商店,所以钩子可以跨越调和器边界工作.

import { Client } from "@colyseus/sdk";
import { createLobbyContext, createRoomContext } from "@colyseus/react";

const client = new Client("ws://localhost:2567");

const { LobbyProvider, useLobby } = createLobbyContext<MyMetadata>();
const { RoomProvider, useRoom, useRoomState } = createRoomContext();

包装您的应用程序 LobbyProvider (可与 RoomProvider:

function App() {
  return (
    <LobbyProvider connect={() => client.joinOrCreate("lobby")}>
      <RoomProvider connect={() => client.joinOrCreate("game_room")}>
        <UI />
        <Canvas>
          <GameScene />
        </Canvas>
      </RoomProvider>
    </LobbyProvider>
  );
}

LobbyProvider 接受一个 connect 回调( 和 useLobbyRoom)和可选 deps 阵列。 大厅连接独立于游戏室.

从任何组件访问大厅数据——甚至游戏深处:

function RoomBrowser() {
  const { rooms, error, isConnecting } = useLobby();

  if (isConnecting) return <p>Loading rooms...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <ul>
      {rooms.map((room) => (
        <li key={room.roomId}>
          {room.metadata.displayName} — {room.clients}/{room.maxClients}
        </li>
      ))}
    </ul>
  );
}

回来的 useLobby() 钩子提供与 useLobbyRoom (单位:千美元)rooms, (中文(简体) ), room, (中文(简体) ), error, (中文(简体) ), isConnecting) (中文(简体) ).

贷项

灵感和以前的工作 @ pedr0fontoura (英语) —— 说 使用密码。 。 。 . 重写和新建 useRoomState() (单位:千美元) @FTWinston (英语)。 。 。 .

版本与发布记录

@colyseus/react 共发布 21 个版本,首次发布于 2026/02/10;过去 12 个月发布了 21 个版本。

版本发布日期距今
0.18.4latest2026/10/031 个月前
0.18.32026/10/031 个月前
0.18.22026/08/262 个月前
0.1.192026/08/182 个月前
0.1.182026/08/172 个月前
0.1.172026/06/224 个月前

关于 @colyseus/react 的常见问题

@colyseus/react 是什么?

反应钩 科利赛 多人应用.

如何安装 @colyseus/react?

在项目目录运行 npm install @colyseus/react,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=18.3.1)、@colyseus/sdk(^0.18.2)、@colyseus/schema(^5.0.8)、@colyseus/shared-types(^0.18.1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@colyseus/react 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@colyseus/react 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@colyseus/react 可以商用吗?

@colyseus/react 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@colyseus/react 的下载量有多少?

根据 npm 官方下载统计,@colyseus/react 在 2026/10/11 – 2026/11/09 这 30 天内被下载 2,731 次,日均约 91 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@colyseus/react 还在维护吗?

最新版本 0.18.4 发布于 2026/10/03(1 个月前);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/02/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。