FluX
FluX
TtRPC
Created by coder2000 on 4/10/2025 in #❓-help
Wrong type for results
Afaik you need to use a transformer https://trpc.io/docs/server/data-transformers
5 replies
TtRPC
Created by FluX on 3/23/2025 in #❓-help
v11 types ProcedureBuilder & MiddlewareBuilder
I would do this, but I'm not sure if this might break in the future
type Middleware = MiddlewareBuilder<object, object, object, unknown>
type Procedure = ProcedureBuilder<
object,
object,
object,
typeof unsetMarker,
typeof unsetMarker,
typeof unsetMarker,
typeof unsetMarker,
false
>
type Middleware = MiddlewareBuilder<object, object, object, unknown>
type Procedure = ProcedureBuilder<
object,
object,
object,
typeof unsetMarker,
typeof unsetMarker,
typeof unsetMarker,
typeof unsetMarker,
false
>
3 replies
TtRPC
Created by skaneprime on 3/14/2025 in #❓-help
Type error when following guide TRPC React query: 'lazy' is declared here.
Make sure your server and client are using the exact same version of trpc. That should usually fix errors like this one. (If your versions are already in sync, I unfortunately have no clue what's wrong)
4 replies
TtRPC
Created by Hexi on 3/6/2025 in #❓-help
File based structuring, trpc layout
That's not possible as far as I'm aware. You always need to define the structure of your router in code. One approach that comes close to what you're asking is to create nested routers and organize routers and procedures like so:
trpc/
├── router/
│ ├── admin/
│ │ ├── products/
│ │ │ ├── create.handler.ts
│ │ │ ├── edit.handler.ts
│ │ │ └── index.ts
│ │ └── users/
│ │ ├── edit.handler.ts
│ │ └── index.ts
│ ├── public/
│ │ └── cart/
│ │ ├── addItem.handler.ts
│ │ ├── removeItem.handler.ts
│ │ └── index.ts
│ └── index.ts
└── index.ts
trpc/
├── router/
│ ├── admin/
│ │ ├── products/
│ │ │ ├── create.handler.ts
│ │ │ ├── edit.handler.ts
│ │ │ └── index.ts
│ │ └── users/
│ │ ├── edit.handler.ts
│ │ └── index.ts
│ ├── public/
│ │ └── cart/
│ │ ├── addItem.handler.ts
│ │ ├── removeItem.handler.ts
│ │ └── index.ts
│ └── index.ts
└── index.ts
You'll still need to add your procedures to your routers in code
3 replies
TtRPC
Created by Mr. Joker on 3/6/2025 in #❓-help
I'm trying to get type for queries/mutations returned from trpc use hooks, but they are different
This is how I did it:
import { AppRouter } from "../router"
import { TRPCClientErrorLike } from "@trpc/client"
import { UseTRPCQueryResult } from "@trpc/react-query/shared"
import { inferRouterOutputs } from "@trpc/server"

export type TRPCClientError = TRPCClientErrorLike<AppRouter>

export type TRPCUseQueryResult<TData> = UseTRPCQueryResult<
TData,
TRPCClientError
>

export type RouterOutput = inferRouterOutputs<AppRouter>
import { AppRouter } from "../router"
import { TRPCClientErrorLike } from "@trpc/client"
import { UseTRPCQueryResult } from "@trpc/react-query/shared"
import { inferRouterOutputs } from "@trpc/server"

export type TRPCClientError = TRPCClientErrorLike<AppRouter>

export type TRPCUseQueryResult<TData> = UseTRPCQueryResult<
TData,
TRPCClientError
>

export type RouterOutput = inferRouterOutputs<AppRouter>
interface UserContext {
user: TRPCUseQueryResult<RouterOutput["public"]["user"]["me"]>
}

const UserContext = createContext<UserContext | null>(null)

export const UserProvider = ({ children }: { children: React.ReactNode }) => {
const user = trpc.public.user.me.useQuery()

return (
<UserContext.Provider value={{ user }}>
{children}
</UserContext.Provider>
)
}
interface UserContext {
user: TRPCUseQueryResult<RouterOutput["public"]["user"]["me"]>
}

const UserContext = createContext<UserContext | null>(null)

export const UserProvider = ({ children }: { children: React.ReactNode }) => {
const user = trpc.public.user.me.useQuery()

return (
<UserContext.Provider value={{ user }}>
{children}
</UserContext.Provider>
)
}
And here is the same for the new tanstack-react-query integration:
import { AppRouter, RouterOutput } from "..."
import { TRPCClientErrorLike } from "@trpc/client"
import { UseQueryResult } from "@tanstack/react-query"

export { useTRPC, type RouterOutput }
export type TRPCClientError = TRPCClientErrorLike<AppRouter>
export type TRPCUseQueryResult<T> = UseQueryResult<T, TRPCClientError>
import { AppRouter, RouterOutput } from "..."
import { TRPCClientErrorLike } from "@trpc/client"
import { UseQueryResult } from "@tanstack/react-query"

export { useTRPC, type RouterOutput }
export type TRPCClientError = TRPCClientErrorLike<AppRouter>
export type TRPCUseQueryResult<T> = UseQueryResult<T, TRPCClientError>
interface UserContext {
user: TRPCUseQueryResult<RouterOutput["public"]["user"]["me"]>
}

export const UserProvider = ({ children }: { children: React.ReactNode }) => {
const trpc = useTRPC()
const user = useQuery(trpc.public.user.me.queryOptions())

return (
<UserContext.Provider value={{ user }}>
{children}
</UserContext.Provider>
)
}
interface UserContext {
user: TRPCUseQueryResult<RouterOutput["public"]["user"]["me"]>
}

export const UserProvider = ({ children }: { children: React.ReactNode }) => {
const trpc = useTRPC()
const user = useQuery(trpc.public.user.me.queryOptions())

return (
<UserContext.Provider value={{ user }}>
{children}
</UserContext.Provider>
)
}
You should be able to build types for useMutation the same way. I have no examples for that
7 replies
TtRPC
Created by Jonathan on 2/21/2025 in #❓-help
Where did useUtils go?
useUtils is just a wrapper around Tanstack Query. See https://trpc.io/docs/client/react/useUtils#helpers The new integration uses native Tanstack Query, removing the wrappers. For your case (the fetch call) I believe you must change your code to:
const trpc = useTRPC()
await queryClient.fetchQuery(trpc.contacts.grid.queryOptions())
const trpc = useTRPC()
await queryClient.fetchQuery(trpc.contacts.grid.queryOptions())
8 replies
TtRPC
Created by Adicss on 2/20/2025 in #❓-help
Upgrading tRPC v10 to v11 in NextJS 15.0.1
tRPC requires TypeScript >=5.7.2
It says it at the top of their docs. But I don't know if this will actually fix it. The upgrade you should do anyways
6 replies
TtRPC
Created by IGMTCrypto on 2/19/2025 in #❓-help
Can I use tRPC on multiple platforms?
6 replies
TtRPC
Created by Szymon on 2/7/2025 in #❓-help
error handling
If you went with this approach and used the tryTo function, I think you could check in the catch block if it's a TRPCClientError and return the message.
if (error instanceof TRPCClientError) {
const message = // get message from error
}
if (error instanceof TRPCClientError) {
const message = // get message from error
}
Haven't tried it tho
9 replies
TtRPC
Created by codecret | Software Engineer on 2/15/2025 in #❓-help
correct way to handle errors run time errors
7 replies
TtRPC
Created by codecret | Software Engineer on 2/13/2025 in #❓-help
invalidate query
You could call refetch after you've awaited your mutation. const { refetch } = trpc.user.getUsers.useQuery()
16 replies
TtRPC
Created by Oung Seik on 2/12/2025 in #❓-help
Can't build NextJS with TRPC vanilla client.
I've had similar issues before and it has to do with path aliases in the tsconfig. I think what's happening is that nextjs tries to resolve @/collections inside of the client app folder and not inside the server folder. Unfortunately I don't have a solution for you, since I work around that by avoiding aliases in my trpc routers, though I agree using path aliases is way cleaner for imports.
4 replies
TtRPC
Created by Szymon on 2/7/2025 in #❓-help
error handling
I guess what you're referring to is the little error popup in Next.js. What I like to do is to wrap my mutation call in a try/catch wrapper function and show a toast in case of errors. Not sure if this is the best solution but it works.
import { toast } from "sonner"

type TryFnHandler = () => any | Promise<any>

interface TryFnOptions<T extends TryFnHandler> {
onSuccess?: (result: Awaited<ReturnType<T>>) => void
onError?: (error: unknown) => void
successMessage?: string | ((result: Awaited<ReturnType<T>>) => string)
errorMessage?: string
}

export async function tryTo<T extends TryFnHandler>(
handler: T,
opts: TryFnOptions<T> = {},
) {
try {
const result = await handler()

if (opts.onSuccess) {
opts.onSuccess(result)
}

if (opts.successMessage) {
if (typeof opts.successMessage === "function") {
toast.success(opts.successMessage(result))
} else {
toast.success(opts.successMessage)
}
}
} catch (error) {
if (opts.onError) {
opts.onError(error)
}

if (opts.errorMessage) {
toast.error(opts.errorMessage)
} else {
const message =
error instanceof Error
? error.message
: "Oh no, something went wrong!"
toast.error(message)
}
}
}
import { toast } from "sonner"

type TryFnHandler = () => any | Promise<any>

interface TryFnOptions<T extends TryFnHandler> {
onSuccess?: (result: Awaited<ReturnType<T>>) => void
onError?: (error: unknown) => void
successMessage?: string | ((result: Awaited<ReturnType<T>>) => string)
errorMessage?: string
}

export async function tryTo<T extends TryFnHandler>(
handler: T,
opts: TryFnOptions<T> = {},
) {
try {
const result = await handler()

if (opts.onSuccess) {
opts.onSuccess(result)
}

if (opts.successMessage) {
if (typeof opts.successMessage === "function") {
toast.success(opts.successMessage(result))
} else {
toast.success(opts.successMessage)
}
}
} catch (error) {
if (opts.onError) {
opts.onError(error)
}

if (opts.errorMessage) {
toast.error(opts.errorMessage)
} else {
const message =
error instanceof Error
? error.message
: "Oh no, something went wrong!"
toast.error(message)
}
}
}
const mutation = trpc.yourHandler.useMutation()

async function doMutation {
await tryTo(async () => {
await mutation.mutateAsync()
})
}
const mutation = trpc.yourHandler.useMutation()

async function doMutation {
await tryTo(async () => {
await mutation.mutateAsync()
})
}
9 replies
TtRPC
Created by Ahmed Eid on 2/6/2025 in #❓-help
How to reset the cache without triggering refetches for none active queries ?
4 replies
TtRPC
Created by function on 1/30/2025 in #❓-help
Throw NOT_FOUND on nullish
In my opinion using a wrapper function is your best bet for this. I too would do it this way. Not much of help, I know, just wanted to leave my 2 cents
5 replies
TtRPC
Created by Kamil on 1/27/2025 in #❓-help
What is the substitution for queryKey in useQuery?
If you have a useQuery hook like const hook = trpc.getUsers.useQuery({ username }), where username is a state that's tied to a search input, the query will re-run automatically when username changes. No dependency array needed
3 replies
TtRPC
Created by Michael Schaufelberger on 1/15/2025 in #❓-help
How do *you* structure the tRPC router when dealing with isolated components?
No description
5 replies
TtRPC
Created by Michael Schaufelberger on 1/15/2025 in #❓-help
How do *you* structure the tRPC router when dealing with isolated components?
In my apps I like to follow this structure: I have two top-level routers - an adminRouter and a publicRouter. The adminRouter has many nested routers, e.g. userRouter or productRouter, where each nested router contains CRUD procedures for database entities. Like you, I also have some one-off procedures I need to call in an admin dashboard. For example for clearing caches or for streaming OpenAI response data into an input field. For that I decided to create a systemRouter nested under adminRouter, with routes like /trpc/admin.system.clearCaches or /trpc/admin.system.openaiTranslation. If I'm guessing correctly and you're building a component to display comments of a post, maybe you already have like a commentsRouter or postsRouter where you can put that procedure. Otherwise think of a way to group this (and potential future one-off procedures) into a router.
5 replies
TtRPC
Created by FluX on 11/28/2024 in #❓-help
Possible to build this custom hook?
4 replies