Form 상태 관리, 캐싱, 유효성검사 관련하여 next에서 새롭게 제시하는 solution입니다
Form 데이터로 서버의 데이터를 변경하고, 중간 API 레이어 없이 서버에서 동작하는 함수를 클라이언트에서 직접 실행시킬 수 있습니다
next@13.4.0부터 'beta' 단계가 되었습니다.
클라이언트에서 서버의 함수를 호출할 수 있는 기능입니다. 해당 함수는 아래 3가지 방법으로 호출할 수 있습니다.
import db from './db'
import { redirect } from 'next/navigation'
async function create(formData: FormData){
'use serevr'
const post = await db.post.insert({
title: formData.get('title'),
content: formData.get('content'),
})
redirect(`/blog/${post.slug}`)
}
export default function Page(){
return (
<form action={create}>
<input type="text" name="title" />
<textarea name="content" />
<button type="submit">Submit</button>
</form>
)
}
export default function Page() {
async function handleSubmit() {
'use server';
// ...
}
async function submitImage() {
'use server';
// ...
}
return (
<form action={handleSubmit}>
<input type="text" name="name" />
<input type="image" formAction={submitImage} />
<button type="submit">Submit</button>
</form>
);
}
client component에서 server action을 호출하는 방법
// app/actions.js
'use server'; // client-component 파일에서 server action 직접 정의할 수 없기 때문에, 따로 파일을 만들어야합니다.
export async function addItem(id) {
await addItemToDb(id);
revalidatePath(`/product/${id}`);
}
// app/components/example-client-component.js
'use client';
import { useTransition } from 'react';
import { addItem } from '../actions';
function ExampleClientComponent({ id }) {
let [isPending, startTransition] = useTransition();
return (
<button onClick={() => startTransition(() => addItem(id))}>
Add To Cart
</button>
);
}
use server
지시문이 있는 함수에 대한 고유 라우팅 경로를 할당합니다. 1. 신기술이라서 간지난다
2. 정의/호출방식이 더 편리함. pages/api 디렉토리 구조에 맞게 경로 작성해서 요청할 필요 없다.
3. 서버 액션, 서버컴포넌트 등의 server only 코드는 클라에 내려주는 JS 번들에 포함되지 않아서, 전체적으로 JS 번들 사이즈가 줄어든다.
4. 사실 확 와닿는 차이는 모르겠다.. 제보 바랍니다.
실험기능이라 아래와 같이 config 파일에 명시해줘야 사용 가능합니다
// next.config.js.
module.exports = {
experimental: {
serverActions: true,
},
};
server action은 use server 지시문을 통해 생성할 수 있습니다.
user server 지시문을 함수 본문 상단에 작성해서 server action으로 만들 수도 있고, 파일 최상단에 위치시켜 파일에서 내보내는 모든 함수를 server action으로 만들 수도 있습니다.
// async function myAction() {
'use server';
// ...
}
or
// myActions.js
export async function myAction1(){
'use server`;
// ..
}
export async function myAction2(){
'use server`;
// ..
}
export async function myAction3(){
'use server`;
// ..
}