Skip to content

feat(web): wire tRPC React Query client and retire the vanilla stub - #381

Merged
blockchain-maxis merged 2 commits into
blockchain-maxis:mainfrom
ntttttbl123-blip:feat/trpc-react-query-225
Sep 3, 2026
Merged

feat(web): wire tRPC React Query client and retire the vanilla stub#381
blockchain-maxis merged 2 commits into
blockchain-maxis:mainfrom
ntttttbl123-blip:feat/trpc-react-query-225

Conversation

@ntttttbl123-blip

Copy link
Copy Markdown
Contributor

Closes #225.

What

Replaces the vanilla tRPC stub with the real @trpc/react-query integration so client components get caching, request deduplication, and invalidation.

  • lib/trpc.ts — now exports a createTRPCReact<AppRouter>() client (typed useQuery/useMutation hooks); the TODO(signet) and the old vanilla client are retired.
  • lib/trpc-provider.tsx (new) — a 'use client' TRPCProvider mounting QueryClientProvider + the tRPC provider. The QueryClient and tRPC client are created via useState initialisers (per-mount, not module scope) so one request's cache can't leak into another's server render.
  • app/(dashboard)/layout.tsx — wraps the authenticated dashboard children in <TRPCProvider> (only when signed in).
  • app/(dashboard)/app/profile/profile-editor.tsx — migrated from the hand-rolled useEffect/.query()/.mutate() to account.me.useQuery() + account.update.useMutation(). A successful save now invalidates account.me, so the profile refetches instead of holding stale values. The loading / error / no-profile / ready states and the "configured database" and "claim a handle first" messages are preserved.
  • lib/trpc-client.ts — deleted; the dashboard's only consumer now uses the React Query client.
  • package.json — adds @trpc/react-query and @tanstack/react-query; lockfile updated.

Public read surfaces stay server-rendered and call the profile helpers directly — the client is only for the authenticated dashboard.

Verification

  • pnpm --filter @signet/web typecheck — clean
  • pnpm --filter @signet/web lint — clean
  • pnpm --filter @signet/web test — 207 passing
  • pnpm --filter @signet/web build — succeeds

@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@ntttttbl123-blip Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@netlify

netlify Bot commented Aug 31, 2026

Copy link
Copy Markdown

Deploy Preview for stellar-signet ready!

Name Link
🔨 Latest commit 2c8ddd5
🔍 Latest deploy log https://app.netlify.com/projects/stellar-signet/deploys/6a99569f54ee4c00080627d8
😎 Deploy Preview https://deploy-preview-381--stellar-signet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

@ntttttbl123-blip is attempting to deploy a commit to the blockchainmaxis-8449's projects Team on Vercel.

A member of the Team first needs to authorize it.

@blockchain-maxis blockchain-maxis left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the migration the TODO in lib/trpc.ts was asking for, and the details are right. Creating the QueryClient and tRPC client in useState initialisers instead of at module scope — with the comment explaining that a module-level client would be shared across server requests and leak one user's cache into another's render — is the part people usually get wrong. The seeded ref so a post-save refetch can't clobber in-flight edits, and invalidate() on success so other readers see the edit, are both correct.

Two problems, both from the branch being based on 8216232.

1. Deleting lib/trpc-client.ts breaks a second caller that landed since. #333 ("feat(web): let a wallet be unlinked from the dashboard") added apps/web/app/(dashboard)/app/wallets/unlink-wallet-button.tsx, which does:

import { trpc } from '@/lib/trpc-client';

Your PR removes that module and migrates only profile-editor.tsx, so after a rebase the wallets page won't resolve its import. unlink-wallet-button.tsx needs the same treatment — trpc.account.unlinkWallet.useMutation() in place of the vanilla .mutate() call — and it will need to be inside TRPCProvider, which your (dashboard)/layout.tsx change already covers.

2. lib/trpc.ts conflicts.

CONFLICT (content): Merge conflict in apps/web/lib/trpc.ts
CONFLICT (content): Merge conflict in pnpm-lock.yaml

#316 landed an hour ago and rewrote getBaseUrl() in that file to go through appUrl() from lib/public-env.ts, so the server-side branch returns the guarded origin rather than a raw process.env read. Your version replaces the whole module with createTRPCReact<AppRouter>(), which has no transport and therefore no base URL at all.

That's fine if nothing calls tRPC from the server — and as far as I can tell nothing does; the two importers are both client components, and the public read surfaces call the profile helpers directly, as your doc comment says. Worth stating that explicitly in the PR description though, because it means #316's appUrl() wiring in trpc.ts becomes dead code that this PR is deliberately dropping rather than accidentally reverting. If it turns out something does need a server-side caller later, it should be a separate server-only module, not this one.

The lockfile conflict is just main having moved; regenerate it after the rebase.

Rebase onto main, migrate unlink-wallet-button.tsx, and I'll take it.

Resolves the conflicts between the React Query tRPC migration and main:

- apps/web/lib/trpc.ts: keep the createTRPCReact client. Main had
  rewritten the vanilla client's getBaseUrl to use appUrl(); that whole
  code path is retired here, so the appUrl import goes with it. The
  transport lives in trpc-provider.tsx against a relative /api/trpc.
- pnpm-lock.yaml: regenerated from main's lockfile rather than merged by
  hand, so main's @trezor/* bump is preserved while @trpc/react-query and
  @tanstack/react-query are added.
- apps/web/app/(dashboard)/app/wallets/unlink-wallet-button.tsx: main
  added this after the PR branched, and it imported the deleted
  lib/trpc-client. Migrated to trpc.account.unlinkWallet.useMutation()
  with the same two-step confirm, pending label and error handling, and
  it now invalidates account.me alongside router.refresh().
@blockchain-maxis
blockchain-maxis merged commit 6fc0c52 into blockchain-maxis:main Sep 3, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tRPC client is a stub with no React Query integration

2 participants