ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • form에서 server action 다루기
    FrontEnd/Next.js 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)}
Designed by Tistory.