@@ -14,8 +14,8 @@ Main Process (Node.js) Renderer Process (React)
1414│ └── ... │ │ └── TaskService, ... │
1515├───────────────────────┤ ├───────────────────────────┤
1616│ tRPC Routers │ ◄─tRPC(ipcLink)─► │ tRPC Clients │
17- │ (use DI services) │ │ ├── trpcReact (hooks) │
18- ├───────────────────────┤ │ └── trpcVanilla │
17+ │ (use DI services) │ │ ├── useTRPC() (hooks) │
18+ ├───────────────────────┤ │ └── trpcClient (vanilla) │
1919│ System I/O │ ├───────────────────────────┤
2020│ (fs, git, shell) │ │ Zustand Stores (state) │
2121│ STATELESS │ │ ├── taskStore │
@@ -166,27 +166,84 @@ export const trpcRouter = router({
166166
167167### Using tRPC in Renderer
168168
169- ** React hooks:**
169+ There are three tRPC exports, each for a different context:
170+
171+ | Export | Where to use | Purpose |
172+ | --------| -------------| ---------|
173+ | ` useTRPC() ` | React components/hooks | Options proxy via React context |
174+ | ` trpc ` | Outside React (module scope, services, stores) | Options proxy bound to the singleton ` queryClient ` |
175+ | ` trpcClient ` | Anywhere (imperative calls) | Vanilla tRPC client for direct ` .query() ` / ` .mutate() ` / ` .subscribe() ` |
176+
177+ ** React components** use ` useTRPC() ` + TanStack Query hooks:
170178
171179``` typescript
172- import { trpcReact } from " @renderer/trpc/client" ;
180+ import { useTRPC } from " @renderer/trpc/client" ;
181+ import { useMutation , useQuery } from " @tanstack/react-query" ;
173182
174183function MyComponent() {
175- // Queries
176- const { data } = trpcReact .my .getData .useQuery ({ id: " 123" });
177-
178- // Mutations
179- const mutation = trpcReact .my .updateData .useMutation ();
184+ const trpc = useTRPC ();
185+
186+ // Queries — pass queryOptions() to useQuery
187+ const { data } = useQuery (
188+ trpc .my .getData .queryOptions ({ id: " 123" }),
189+ );
190+
191+ // Mutations — pass mutationOptions() to useMutation
192+ const mutation = useMutation (
193+ trpc .my .updateData .mutationOptions ({
194+ onSuccess : () => { /* ... */ },
195+ }),
196+ );
180197 const handleUpdate = () => mutation .mutate ({ id: " 123" , value: " new" });
181198}
182199```
183200
184- ** Outside React (vanilla client): **
201+ ** Subscriptions ** use ` useSubscription ` from ` @trpc/tanstack-react-query ` :
185202
186203``` typescript
187- import { trpcVanilla } from " @renderer/trpc/client" ;
204+ import { useSubscription } from " @trpc/tanstack-react-query" ;
205+
206+ useSubscription (
207+ trpc .my .onItemCreated .subscriptionOptions (undefined , {
208+ onData : (item ) => { /* ... */ },
209+ }),
210+ );
211+ ```
212+
213+ ** Cache invalidation** uses ` pathFilter() ` or ` queryFilter() ` with the query client:
188214
189- const data = await trpcVanilla .my .getData .query ({ id: " 123" });
215+ ``` typescript
216+ const queryClient = useQueryClient ();
217+
218+ // Invalidate all queries under a router path
219+ queryClient .invalidateQueries (trpc .workspace .getAll .pathFilter ());
220+
221+ // Invalidate a specific query by input
222+ queryClient .invalidateQueries (
223+ trpc .git .getCurrentBranch .queryFilter ({ directoryPath: repoPath }),
224+ );
225+
226+ // Set cache data directly
227+ queryClient .setQueryData (
228+ trpc .git .getLatestCommit .queryKey ({ directoryPath: repoPath }),
229+ commitData ,
230+ );
231+ ```
232+
233+ ** Outside React** (stores, sagas, services, module-scope utilities):
234+
235+ ``` typescript
236+ // Imperative calls — use trpcClient
237+ import { trpcClient } from " @renderer/trpc/client" ;
238+
239+ const data = await trpcClient .my .getData .query ({ id: " 123" });
240+ await trpcClient .my .updateData .mutate ({ id: " 123" , value: " new" });
241+
242+ // Cache operations outside React — use trpc (the module-level options proxy)
243+ import { trpc } from " @renderer/trpc" ;
244+ import { queryClient } from " @utils/queryClient" ;
245+
246+ queryClient .invalidateQueries (trpc .workspace .getAll .pathFilter ());
190247```
191248
192249## State Management
@@ -308,7 +365,7 @@ This pattern provides:
3083653 . ** Register service** in ` src/main/di/container.ts `
3093664 . ** Create tRPC router** in ` src/main/trpc/routers/ `
3103675 . ** Add router** to ` src/main/trpc/router.ts `
311- 6 . ** Use in renderer** via ` trpcReact ` hooks
368+ 6 . ** Use in renderer** via ` useTRPC() ` + TanStack Query hooks
312369
313370## Events (tRPC Subscriptions)
314371
@@ -409,25 +466,32 @@ export const shellRouter = router({
409466### 4. Subscribe in Renderer
410467
411468``` typescript
469+ import { useSubscription } from " @trpc/tanstack-react-query" ;
470+
471+ const trpc = useTRPC ();
472+
412473// React component - global events
413- trpcReact .my .onItemCreated .useSubscription (undefined , {
414- enabled: true ,
415- onData : (item ) => {
416- // item is typed as { id: string; name: string }
417- console .log (" Created:" , item );
418- },
419- });
474+ useSubscription (
475+ trpc .my .onItemCreated .subscriptionOptions (undefined , {
476+ enabled: true ,
477+ onData : (item ) => {
478+ // item is typed as { id: string; name: string }
479+ },
480+ }),
481+ );
420482
421483// React component - per-session events
422- trpcReact .shell .onData .useSubscription (
423- { sessionId },
424- {
425- enabled: !! sessionId ,
426- onData : (event ) => {
427- // event is typed as { sessionId: string; data: string }
428- terminal .write (event .data );
484+ useSubscription (
485+ trpc .shell .onData .subscriptionOptions (
486+ { sessionId },
487+ {
488+ enabled: !! sessionId ,
489+ onData : (event ) => {
490+ // event is typed as { sessionId: string; data: string }
491+ terminal .write (event .data );
492+ },
429493 },
430- } ,
494+ ) ,
431495);
432496```
433497
0 commit comments