NEXT.js

[Next.js] react 와 next의 form submit 차이( Server Actions 시 )

머지?는 병합입니다 2024. 11. 28. 14:00

 

기존 react 에서 form 제출 시에는 

export default function Signup() {


  function handleSubmit(e) {
    e.preventDefault()

    const formData = new FormData(e.target)
    console.log('formData', formData)
    const acquisitionChoices = formData.getAll('acquisition')
    const data = Object.fromEntries(formData.entries())
    data.acquisition = acquisitionChoices

  }

  return (
    <form onSubmit={handleSubmit}>
     
      <div className="control">
        <label htmlFor="email">Email</label>
        <input id="email" type="email" name="email" required/>    
      </div>

      <p className="form-actions">
        <button type="reset" className="button button-flat">
          Reset
        </button>
        <button type="submit" className="button">
          Sign up
        </button>
      </p>
    </form>
  );
}

 

 

이런 식으로 FormData 메서드를 직접 사용했지만

기존 방식의 Client-side 이 아닌 Server Actions 사용하는 경우 달리 구성해야 합니다.

( 물론 특별한 컨벤션이 없다면, 기존 react 의 Client-side 방식으로도 사용해도 됩니다 )

 

 

 Server Actions 의 경우

 

// SubmitPage.js
import classes from './page.module.css';

export default function SubmitPage() {

  // 데이터 전송 함수 server action
  async function submit(formData){ // 1 
    'use server' // 2

    const test = {
      title: formData.get('title'),
      summary: formData.get('summary'),
      instructions: formData.get('instructions'),
      image: formData.get('image'),
      creator: formData.get('name'),
      creator_email: formData.get('email'),
    }
    console.log('submitted test', test);
  }
  return (
    <>
      <header className={classes.header}>
        <h1>
          test <span className={classes.highlight}>code</span>
        </h1>
      </header>
      <main className={classes.main}>
        {/* 통상적인 aciotn 에 url 이 들어가는 게 아니다 */}
        <form className={classes.form} action={submit}>
          <div className={classes.row}>
            <p>
              <label htmlFor="name">Your name</label>
              <input type="text" id="name" name="name" required />
            </p>
            <p>
              <label htmlFor="email">Your email</label>
              <input type="email" id="email" name="email" required />
            </p>
          </div>
                {/* 중간 생략 */}
          <p className={classes.actions}>
            <button type="submit">summit</button>
          </p>
        </form>
      </main>
    </>
  );
}

 

1. SubmitPage 함수 안에 submit 함수를 만들고

2. submit 함수는 비동기 함수로 만들어줍니다 ( async )

3. <form action={submit}>  action 에는 submit 함수를 바인딩 해주고

4. 비동기 함수 submit 안에서 'use client' 지정을 해준 후

5. submit 함수의 파라미터로 자동으로 넘어오는 formdata를 사용하면 됩니다

 

기존 react 처럼

const formData = new FormData(e.target) 이렇게 별도로 선언을 안해도 되며

물론 각 input tag 에는 name 속성이 있어야 합니다

 

 

그리고 이러한 server action 메서드를 JSX와 함께 두는 것 보단 외부로 모듈링 하는 게 더 나은 선택일 수 있습니다.

단일 책임 원칙도 있겠지만, 차 후에 SubmitPage 컴포넌트가 Client-side로 변경 된다면 use client 와 use server는

한 파일에 동시에 선언이 불가하여 잠재적 오류의 가능성이 있기 때문 입니다.

 

 

// SubmitPage.js

import classes from './page.module.css';
import { submit } from '@/lib/actions';

export default function SubmitPage() {
  return (
    <>
      <header className={classes.header}>
        <h1>
          test <span className={classes.highlight}>code</span>
        </h1>
      </header>
      <main className={classes.main}>
        {/* 통상적인 aciotn 에 url 이 들어가는 게 아니다 */}
        <form className={classes.form} action={submit}>
          <div className={classes.row}>
            <p>
              <label htmlFor="name">Your name</label>
              <input type="text" id="name" name="name" required />
            </p>
            <p>
              <label htmlFor="email">Your email</label>
              <input type="email" id="email" name="email" required />
            </p>
          </div>
                {/* 중간 생략 */}
          <p className={classes.actions}>
            <button type="submit">summit</button>
          </p>
        </form>
      </main>
    </>
  );
}

 

// actions.js

'use server'

 // 데이터 전송 함수 server action
export async function submit(formData){
  const test = {
    title: formData.get('title'),
    summary: formData.get('summary'),
    instructions: formData.get('instructions'),
    image: formData.get('image'),
    creator: formData.get('name'),
    creator_email: formData.get('email'),
  }
  console.log('submitted test', test);
}

 

 

 

그럼 이렇게 ide 터미널에서 log 확인을 할 수 있습니다.

( Client-side 가 아니므로 브라우저에서는 확인이 안됩니다 )