I have a create-t3-app built and I'm having trouble with hooks when creating records with Prisma. I'm trying to use a web form with two simple text fields to insert a record.
The full error seems to be related to the .create() function line const itemAdd = ...
Unhandled Runtime Error TypeError: hooks[lastArg] is not a function
I have also seen the error
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
** index.tsx **
import Head from "next/head";
import { api } from "~/utils/api";
import React, { FormEvent, ReactNode } from "react";
export default async function Home() {
async function handleSubmit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
/* THE hooks[lastArg] is not a function ERROR SEEMS TO COME UP AT THE .create() on the following line: */
const itemAdd = await api.item.create({
data: {
name: (e.currentTarget.elements.namedItem("name") as HTMLInputElement)
.value,
isbn: (e.currentTarget.elements.namedItem("isbn") as HTMLInputElement)
.value,
},
// include: { id: true }, // Returns all fields for all posts
});
console.log(itemAdd.id);
}
return (
<>
<Head>
<title>lectura.io</title>
<meta name="description" content="" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex min-h-screen flex-col items-center justify-center">
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 ">
<h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">
This is cool
</h1>
</div>
<form onSubmit={handleSubmit}>
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 ">
<div>
name: <input type="text" name="name" className="border-2" />
</div>
<div>
isbn: <input type="text" name="isbn" placeholder="isbn" />
</div>
<button type="submit">Submit</button>
</div>
</form>
</main>
</>
);
}
** UPDATE: Adding the code for the ctx.db.item.create() below ** ** item.ts (router) **
import { z } from "zod";
import {
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "~/server/api/trpc";
import { api } from "~/utils/api";
export const itemRouter = createTRPCRouter({
getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
return ctx.db.item.findFirst({
where: {
id: input,
},
});
}),
create: publicProcedure
.input(
z.object({
name: z.string(),
isbn: z.string(),
}),
)
.mutation(async ({ ctx, input }) => {
//const userId = ctx.session.user.id;
try {
const item = await ctx.db.item.create({
data: {
name: input.name,
isbn: input.isbn,
},
});
return item;
} catch (error) {
console.log(error);
}
}),
});
I have tried all combinations I can think of for async/await declarations/usage, and I've also tried the async function handleSubmit inside and outside of the Home() function.
Any help is greatly appreciated!
*** EDIT: Adding more code *** ** api.ts **
import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import superjson from "superjson";
import { type AppRouter } from "~/server/api/root";
const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
};
/** A set of type-safe react-query hooks for your tRPC API. */
export const api = createTRPCNext<AppRouter>({
config() {
return {
transformer: superjson,
links: [
loggerLink({
enabled: (opts) =>
process.env.NODE_ENV === "development" ||
(opts.direction === "down" && opts.result instanceof Error),
}),
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
};
},
ssr: false,
});
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<AppRouter>;
** root.ts **
import { exampleRouter } from "~/server/api/routers/example";
import { createTRPCRouter } from "~/server/api/trpc";
import { itemRouter } from "./routers/item";
/**
* This is the primary router for your server.
* All routers added in /api/routers should be manually added here.
*/
export const appRouter = createTRPCRouter({
example: exampleRouter,
item: itemRouter,
});
// export type definition of API
export type AppRouter = typeof appRouter;
This looks like an error related to tRPC. If you are using mutation hooks, you must do it like so:
More info here.