I am learning Nextjs and i need to pass a variable through a form component, and then further through its server action component. (i think this is called prop drilling and i dont know if theres a more elegant way to do it..) It is needed for the database query. i am working loosly on a tutorial.
Please excuse super naive mistakes since i am a beginner. So im sure there are other mistakes in it, but i am focusing on accessing this fetchuserid value for my db entry:
So here is my page.tsx:
i need to pass fetchuserid through AddBalanceForm
import { fetchUser } from "@/app/components/fetchdata";
import type { UsersDb } from "@/app/components/definitions";
import ThisUserTable from "@/app/components/thisusertable";
import AddBalanceForm from "@/app/components/addbalanceform";
export default async function Page({ params: { slug } }) {
const fetchuserid = Number(slug);
const user: UsersDb = await fetchUser(fetchuserid);
return (
<main>
<ThisUserTable user={user} />
<AddBalanceForm fetchuserid={fetchuserid}/>
</main>
);
}
addbalanceform.tsx
'use client';
import { useFormState } from "react-dom";
import { userAddBalance } from "./adddata";
import SubmitButton from "./submit-button";
import { EMPTY_FORM_STATE } from "./utils";
import { FieldError } from "./utils";
import { useToastMessage } from "./use-toast-message";
import { useFormReset } from "./useformreset";
export default function AddBalanceForm ({ fetchuserid }: { fetchuserid: number }) {
const [formState, action] = useFormState(
userAddBalance,
EMPTY_FORM_STATE,
);
const noScriptFallback = useToastMessage(formState);
const formRef = useFormReset(formState);
return (
<form action={action} className="flex flex-col gap-y-2" ref={formRef}>
<label htmlFor="amount">amount</label>
<textarea id="amount" name="amount" className="border-2" />
<span className="text-xs text-red-400">
<FieldError formState={formState} name="text" />
</span>
<SubmitButton label="Create" loading="Creating ..." />
<span className="font-bold">{formState.message}</span>
{noScriptFallback}
</form>
);
};
the server action is this:
'use server';
import { z } from 'zod';
import { revalidatePath } from 'next/cache';
import BetterSqlite3 from 'better-sqlite3';
import { FormState, toFormState } from './utils';
let db : BetterSqlite3.Database;
db = new BetterSqlite3("./coffeev1.db");
const addBalanceSchema = z.object({
amount: z
.coerce
.number()
.min(1)
.max(1000),
});
export async function userAddBalance(
formState: FormState,
formData: FormData,
fetchuserid: number,
) {
// Insert data into the database
try {
const { amount } = addBalanceSchema.parse({
amount: formData.get('amount')
});
const amountInCents = amount * 100;
const writeuser = db.prepare(
`
UPDATE user_registry
SET kaffeestand = ${amountInCents}
WHERE id = ?1
`);
writeuser.run( { 1: fetchuserid});
} catch (error) {
console.error('Database Error:', error);
}
// Revalidate the cache for the page and redirect the user.
revalidatePath(`/users/${fetchuserid}`);
return toFormState('SUCCESS', 'Message created');
}
now i dont know how to pass the prop to the server action. i think it needs to go in this block:
export default function AddBalanceForm ({ fetchuserid }: { fetchuserid: number }) {
const [formState, action] = useFormState(
userAddBalance,
EMPTY_FORM_STATE,
);
....
thank you for your help.
greetings
idontknowwhatimdoing is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.