FrontEnd/Next.js
form에서 server action 다루기
위그든씨
2024. 6. 15. 01:12
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
form action에서 server action을 하기 위해서는 비동기 함수를 넘겨주면서 use server를 입력해주면 됨
export default function Page() {
async function createInvoice(formData: FormData) {
'use server';
const rawFormData = {
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
};
console.log(rawFormData);
// mutate data
// revalidate cache
}
return (
<div className="flex justify-center items-center max-w-xl ">
<form className="flex flex-col space-y-4" action={createInvoice}>
<input className="border" type="text" name="customerId" />
<input className="border" type="text" name="amount" />
<input className="border" type="text" name="status" />
<button type="submit">submit</button>
</form>
</div>
);
}
만약 클라이언트 쪽에서 서버 액션을 다뤄야한다면 해당 컴포넌트를 분리해야 할 필요가 있다.
import { createInvoice } from './_action';
import ClientPage from './_components/clientPage';
export default function Page() {
return (
<div className="flex justify-center items-center max-w-xl ">
<ClientPage createInvoice={createInvoice} />
</div>
);
}
'use client';
interface ClientPageProps {
createInvoice: (data: FormData) => void;
}
export default function ClientPage({ createInvoice }: ClientPageProps) {
return (
<form className="flex flex-col space-y-4" action={createInvoice}>
<input className="border" type="text" name="customerId" />
<input className="border" type="text" name="amount" />
<input className="border" type="text" name="status" />
<button type="submit">submit</button>
</form>
);
}
'use server';
export async function createInvoice(formData: FormData) {
const rawFormData = {
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
};
console.log(rawFormData);
// mutate data
// revalidate cache
}
만약 server action을 요하는 함수에서 FormData이외 props가 필요할 경우 아래처럼 코드 짜주기
// server action
'use server';
export async function createInvoice(userId: string, data: FormData) {
console.log(data);
console.log(userId);
// mutate data
// revalidate cache
}
// clientComponent.tsx
'use client';
import { createInvoice } from '../_action';
export default function ClientPage() {
const userId = 'someUserId'; // Replace with actual user ID fetching logic
const createInvoiceWithUserId = createInvoice.bind(null, userId);
return (
<form
className="flex flex-col space-y-4"
action={createInvoiceWithUserId}
>
<input className="border" type="text" name="customerId" />
<input className="border" type="text" name="amount" />
<input className="border" type="text" name="status" />
<button type="submit">submit</button>
</form>
);
}
물론 아래처럼 코드를 짜도 됨.
action={(d) => createInvoice('someUserId', d)}