[Next.js] react 와 next의 form submit 차이( Server Actions 시 )
기존 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 가 아니므로 브라우저에서는 확인이 안됩니다 )