Loading...
Loading...
Use when building or debugging React interfaces in Meteor 3: meteor create --react, createRoot, JSX or TSX entry points, Rspack React detection, Fast Refresh, react-meteor-data, useTracker, useSubscribe, useFind, withTracker, Suspense, and Tracker.withComputation. Triggers on isLoading being treated as a boolean, useFind receiving fetch(), stale closure inputs, duplicate tracker side effects, unstable Suspense keys, lost reactivity after await, state reset after refresh, or React tests leaking computations. Use this skill when the user asks about a React skeleton, React-specific rspack.config rules, reactive data hooks, or classic versus Suspense integration. Route general bundler configuration to meteor-modern-build-stack and Meteor 2 upgrades to migrate-to-meteor-3.
npx skill4agent add meteor/agent-skills meteor-reactmeteor create --react <name>meteor create --typescript <name>package.json.meteor/packages.meteor/versionsrspack.config.*react-meteor-dataMeteor.startupcreateRootreact-meteor-datauseSubscribeuseFinduseTrackermeteor create --react my-app
cd my-app
meteorreact-meteor-data.meteor/versionsreferences/react-meteor-data.mdimport { 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 />);
});client/main.tsxtsconfig.jsonrspack.config.ts| Need | API | Contract |
|---|---|---|
| Subscription readiness | Classic | Returns an |
| Reactive list | Classic | Return a cursor, never |
| User, count, single document, ReactiveVar | Classic | Return the reactive value. Avoid arbitrary side effects. |
| Async value with Suspense | Suspense | Supply a stable key and Promise-producing function. |
| SSR-capable collection query | Suspense | Pass the collection and the |
| Existing class component | | Keep it during focused maintenance; plan hooks separately. |
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>;
}useFinduseTrackerreferences/react-meteor-data.mdskipUpdateimport { 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>
);
}useSubscribereferences/suspense-and-async.mdTracker.withComputationawaitrspack.config.*defineConfig@meteorjs/rspack| Request | Owner |
|---|---|
| React detection, JSX or TSX, React Refresh boundary | This skill |
General | |
| Convert an existing app or legacy build plugin to Rspack | |
Meteor-bundler HMR or custom | Build skill, then this skill for React symptoms |
react-fast-refreshhot-module-replacementreferences/build-refresh-and-testing.mdMeteor.callAsyncisLoadingTasks.find().fetch()useFinduseFinduseTrackerawait@rspack/plugin-react-refreshreact-meteor-datameteor/react-packagescreateRootreferences/react-meteor-data.mdreferences/suspense-and-async.mdreferences/build-refresh-and-testing.mdreferences/eval-cases.md