FluX
FluX7d ago

Possible to build this custom hook?

Hello! I'm facing a challenge and hope to get some guidance here. I'm building an admin dashboard for creating and editing data - let's just say it's product data. I built a product management form that I want to use for both creating and editing a product, because the fields are the same. I'd like to build a custom hook which returns multiple useQuerys or useMutations for a tRPC route. The hook might look like this:
// single query/mutation
const mutation = useApi((router) => router.admin.product.edit)
const query = useApi((router) => router.public.product.details)
// or multiple hooks for a router
const { editMutation, createMutation } = useApi((router) => router.admin.product)
// ^
// | with type error, if tRPC route (e.g. `admin.product.edit`) does not exist
// single query/mutation
const mutation = useApi((router) => router.admin.product.edit)
const query = useApi((router) => router.public.product.details)
// or multiple hooks for a router
const { editMutation, createMutation } = useApi((router) => router.admin.product)
// ^
// | with type error, if tRPC route (e.g. `admin.product.edit`) does not exist
I've tried creating such a hook but it's not very great and absolutely not type-safe. Any idea how this could be properly implemented? Would appreciate any help :)
export const useManager = <FormData extends FieldValues>(
router: keyof AppRouter["admin"],
dataMode: "create" | "edit"
) => {
const nextRouter = useRouter()

function getMutation(): UseTRPCMutationResult<FormData, any, any, any> {
if (dataMode === "create") {
// @ts-ignore
return trpc.admin[router].create.useMutation()
} else {
// @ts-ignore
return trpc.admin[router].edit.useMutation()
}
}

const mutation = getMutation()

async function submit(data: FormData) {
return await mutation.mutateAsync(data) as FormData
}

// @ts-ignore
const deleteMutation: UseTRPCMutationResult<FormData, any, any, any> = trpc.admin[router].delete.useMutation()

async function purge(slug: string) {
return await deleteMutation.mutateAsync({ slug })
}

const isLoading = mutation.isPending || deleteMutation.isPending

return { submit, isLoading, redirect: nextRouter.push, purge }
}
export const useManager = <FormData extends FieldValues>(
router: keyof AppRouter["admin"],
dataMode: "create" | "edit"
) => {
const nextRouter = useRouter()

function getMutation(): UseTRPCMutationResult<FormData, any, any, any> {
if (dataMode === "create") {
// @ts-ignore
return trpc.admin[router].create.useMutation()
} else {
// @ts-ignore
return trpc.admin[router].edit.useMutation()
}
}

const mutation = getMutation()

async function submit(data: FormData) {
return await mutation.mutateAsync(data) as FormData
}

// @ts-ignore
const deleteMutation: UseTRPCMutationResult<FormData, any, any, any> = trpc.admin[router].delete.useMutation()

async function purge(slug: string) {
return await deleteMutation.mutateAsync({ slug })
}

const isLoading = mutation.isPending || deleteMutation.isPending

return { submit, isLoading, redirect: nextRouter.push, purge }
}
Solution:
GitHub
Possible to build a dynamic useApi hook? · trpc trpc · Discussion #...
Hello! I'm facing a challenge and hope to get some guidance here. I'm building an admin dashboard for creating and editing data - let's just say it's product data. I built a product...
Jump to solution
1 Reply
Solution
FluX
FluX7d ago
GitHub
Possible to build a dynamic useApi hook? · trpc trpc · Discussion #...
Hello! I'm facing a challenge and hope to get some guidance here. I'm building an admin dashboard for creating and editing data - let's just say it's product data. I built a product...