mcpField
M
meteor-react

meteor-react

github.com/meteor开发10283 次安装5 天前更新
代码仓库

关于 meteor-react

meteor-react 是一项面向 Meteor 3 应用构建 React 界面的技能,涵盖响应式数据 Hook、渲染、构建配置、数据变更和浏览器测试。

主要功能

  1. 01挂载 React 根节点
  2. 02选择 react-meteor-data Hook
  3. 03显示 Tracker 响应式列表
  4. 04处理 Suspense 与异步数据
  5. 05配置 Rspack 和 React Refresh
  6. 06在浏览器中测试界面行为

适用场景

  1. 01创建 Meteor 3 React 应用
  2. 02根据订阅状态显示界面
  3. 03实现响应式任务列表
  4. 04测试 Meteor 界面行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/meteor/agent-skills --skill meteor-react

安装后在 Claude Code 中输入/meteor-react确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
build-refresh-and-testing.md
eval-cases.md
react-meteor-data.md
suspense-and-async.md

详细介绍

Meteor 3 的 React 界面

React 负责渲染和本地 UI 状态;Meteor 负责响应式数据和构建交接。组件使用经过授权的数据并调用方法。发布和方法仍由服务器掌控。

决策流程

  1. 对于新的 JavaScript 应用,运行 meteor create --react <name>;React 也是默认骨架。对于 TypeScript 和 TSX,运行 meteor create --typescript <name>。
  2. 检查 package.json、.meteor/packages、.meteor/versions、客户端入口和 rspack.config.*。骨架和 react-meteor-data 版本可以独立变化。
  3. 使用 createRoot,从 Meteor.startup 挂载一个 React 根节点。
  4. 为组件选择一种 react-meteor-data 接口:
    • 经典 Hooks:用于显式加载 UI 和同步 Minimongo 读取。
    • 仅当上游 Suspense fallback 和拒绝边界已负责处理挂起和错误状态时,才使用 Suspense Hooks。
  5. 使用 useSubscribe 获取就绪状态,使用 useFind 获取具有稳定文档引用的响应式列表,其他 Tracker 值则使用 useTracker。
  6. 在此处保留 React 专用的 Rspack 规则。路由别名、加载器、代码拆分、缓存、输出或迁移工作应交由构建技能处理。
  7. 在浏览器支持的客户端测试套件中测试 UI 行为,并始终卸载已渲染的根节点,以便停止 Tracker 计算和订阅。

当前脚手架

meteor create --react my-app
cd my-app
meteor

当前 Meteor 3.4+ 脚手架使用 Rspack 和 react-meteor-data。检查 .meteor/versions:Meteor 3 要求版本为 3.0.0+,这些示例以 4.0.1 为目标,而 references/react-meteor-data.md 记录了各项功能所需的最低版本。

import { Meteor } from "meteor/meteor";
import { createRoot } from "react-dom/client";
import { App } from "/imports/ui/App";
import "/imports/ui/styles.css";

Meteor.startup(() => {
  const container = document.getElementById("react-target");
  if (!container) throw new Error("Missing #react-target");
  createRoot(container).render(<App />);
});

TypeScript 使用 client/main.tsx、tsconfig.json,通常还会使用 rspack.config.ts。Meteor 会直接发现该 TypeScript 配置。

响应式数据选择

需求API契约
订阅就绪状态经典 useSubscribe返回一个 isLoading 函数。调用它。
响应式列表经典 useFind返回游标,绝不要调用 fetch()。
用户、计数、单个文档、ReactiveVar经典 useTracker返回响应式值。避免任意副作用。
带 Suspense 的异步值Suspense useTracker提供稳定键和生成 Promise 的函数。
支持 SSR 的集合查询Suspense useFind传入集合和 find 参数元组。
现有类组件withTracker在有针对性的维护期间保留它;单独规划 Hooks 迁移。

经典列表脚手架:

import { useFind, useSubscribe } from "meteor/react-meteor-data";
import { Tasks } from "/imports/api/tasks";

export function TaskList({ listId }) {
  const isLoading = useSubscribe("tasks.byList", listId);
  const tasks = useFind(
    () => Tasks.find({ listId }, { sort: { createdAt: -1 } }),
    [listId],
  );

  if (isLoading()) return <p>Loading...</p>;
  if (tasks.length === 0) return <p>No tasks.</p>;
  return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
}

useFind 负责游标观察,并且只更新发生变化的文档引用。 如果转换后的聚合结果更清晰,请使用 useTracker。调整依赖项或 skipUpdate 前,请阅读 references/react-meteor-data.md。

Suspense 和异步响应性

Suspense 导入会改变签名;它们不能直接替换:

import { Suspense } from "react";
import { useFind, useSubscribe } from "meteor/react-meteor-data/suspense";
import { Tasks } from "/imports/api/tasks";

function TaskList({ listId }) {
  useSubscribe("tasks.byList", listId);
  const tasks = useFind(Tasks, [
    { listId },
    { sort: { createdAt: -1 } },
  ], [listId]);
  return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
}

export function TaskScreen({ listId }) {
  return (
    <AppErrorBoundary>
      <Suspense fallback={<p>Loading...</p>}>
        <TaskList listId={listId} />
      </Suspense>
    </AppErrorBoundary>
  );
}

将 Suspense useSubscribe 视为仅用于挂起的调用。在当前审查过的 软件包中,其声明的返回类型与运行时值不一致,因此不要使用其返回值。有关稳定键、 拒绝、SSR 以及 await 之后的 Tracker.withComputation,请阅读 references/suspense-and-async.md。

构建与刷新归属

Rspack 会从应用的 npm 依赖中检测 React,启用 JSX 或 TSX 的 SWC 解析,并在客户端开发期间安装和注入 React Refresh。常规的 React Rspack 应用无需手动添加刷新插件。

保持 rspack.config.* 简洁。生成的 JavaScript 骨架展示了一个可选的 SVGR 规则;TypeScript 骨架展示了类型检查。

使用 @meteorjs/rspack 中的 defineConfig 组合自定义规则,同时保留 Meteor 的 SWC 默认配置。

对于 React Compiler,Meteor 3.6-beta.0 组合支持 SWC;较旧的组合可以继续使用 Babel。请阅读编译器设置,了解 React 版本目标和运行时要求。

请求归属
React 检测、JSX 或 TSX、React Refresh 边界此技能
通用 rspack.config 辅助工具、SWC、别名、缓存、代码块meteor-modern-build-stack
将现有应用或旧版构建插件转换为 Rspackmigrate-to-rspack
Meteor-bundler HMR 或自定义 module.hot 生命周期构建技能;React 相关症状则由此技能处理

如果编辑导致页面重新加载或组件状态重置,请先确定哪个打包器编译了该模块。在 Rspack 客户端依赖图中,检查 React Refresh 边界,并避免叠加第二套 react-fast-refresh。在 Meteor-bundler 依赖图中,确认已启用 hot-module-replacement 和捆绑的 React Fast Refresh 集成。请参阅 references/build-refresh-and-testing.md。

变更与测试

在事件处理程序中调用 Meteor.callAsync,在 React 状态中管理等待和拒绝状态,并将验证和授权留在方法内部。不要直接从组件写入敏感集合。

进行测试时,将接收数据作为属性的展示型组件与持有 Hook 的容器分开。使用项目现有的 React 测试库对前者进行单元测试。在浏览器客户端中,使用受控的 Minimongo 或真实发布来测试后者。断言渲染行为,而不是响应式函数的调用次数,因为 React 可能会丢弃工作,并多次调用初始渲染逻辑。

反模式

  • 将经典的 isLoading 视为布尔值。它是一个函数,必须调用。
  • 将 Tasks.find().fetch() 传给 useFind。应返回游标。
  • 在 useFind 工厂中放置订阅。应单独订阅。
  • 在 useTracker 响应式函数中调用 React 状态设置器、方法、分析工具或任意副作用。
  • 强制所有经典组件使用 Suspense。两种用法都仍然适用。
  • 对无关的已挂载计算复用通用 Suspense 键。
  • 在 await 之后读取 Tracker 源,却不恢复计算上下文。
  • 当 Meteor 已经注入 @rspack/plugin-react-refresh 时,仍将其添加到项目配置中。
  • 为添加一个 React 转换而替换所有 Rspack SWC 选项。应扩展它们。
  • 在组件集成测试中完全模拟掉 Meteor 数据行为。

权威资源

评论

支持 Markdown