<aside> 🧪 서버액션은 서버에서 실행 되는 비동기 함수이다. 클라이언트와 서버 컴포넌트에서 모두 사용 되며 Form 태그의 액션과 데이터 변형을 조종한다.
</aside>
"use server" 디렉티브를 명시하여 2가지 방법으로 정의 할 수 있는데, 인라인 함수 레벨과 모듈 레벨에서 사용가능하다.
// 인라인 함수 레벨 예제
// app/page.tsx
export default function Page() {
// Server Action
async function create() {
'use server'
// ...
}
return (
// ...
)
}
// 모듈레벨
// app/actions.ts
'use server'
export async function create() {
// ...
}
"use server" 를 사용한 서버액션만 불러올수있다.//클라이언트 컴포넌트는 오직 모듈레벨 서버액션만 불러올 수 있다.
'use client'
import { create } from '@/app/actions'
export function Button() {
return (
// ...
)
}
prop 으로 전달 할 수 있다.<ClientComponent updateItem={updateItem} />
'use client'
export default function ClientComponent({ updateItem }) {
return <form action={updateItem}>{/* ... */}</form>
}
<Form> 태그의 액션(Submit) 을 서버사이드의 서버 액션에서 처리 해보자HTML <form> 태그 요소를 확장하여 action 속성으로 서버액션을 호출 할 수 있게 해준다. 일단 호출되면 자동으로 FormData 객체를 받고 각각의 폼태그 안의 필드를 추출할 수 있다.
export default function Page() {
async function createInvoice(formData: FormData) {
'use server'
const rawFormData = {
customerId: formData.get('text1'), //foo
amount: formData.get('text2'), //bar
status: formData.get('text3'), //baz
}
}
return
<form action={createInvoice}>
<input type="text" name="text1" value="foo" />
<input type="text" name="text2" value="bar" />
<input type="text" name="text3" value="baz" />
</form>
}
'use client'
//서버 액션 컴포넌트
import { updateUser } from './actions'
export function UserProfile({ userId }: { userId: string }) {
//bind 메소드를 이용하여 추가 매개변수를 서버 액션으로 전달 할 수있다.
const updateUserWithId = updateUser.bind(null, userId)
return (
<form action={updateUserWithId}>
<input type="text" name="name" />
<button type="submit">Update User Name</button>
</form>
)
}
'use server'
//위에서 bind 한 매개변수는 함수의 첫번째 매개변수로 바인딩 된다.
export async function updateUser(userId, formData) {
// ...
}
useFromStatus 훅을 사용하여 Form 태그의 상태를 관찰 할 수 있다.// app/submit-button.tsx
'use client'
import { useFormStatus } from 'react-dom'
export function SubmitButton() {
const { pending } = useFormStatus()
return (
<button type="submit" disabled={pending}>
Add
</button>
)
}
import { SubmitButton } from '@/app/submit-button'
import { createItem } from '@/app/actions'
// Server Component
export default async function Home() {
return (
<form action={createItem}>
<input type="text" name="field-name" />
<SubmitButton />
</form>
)
}