<aside> 🧪 서버액션은 서버에서 실행 되는 비동기 함수이다. 클라이언트와 서버 컴포넌트에서 모두 사용 되며 Form 태그의 액션과 데이터 변형을 조종한다.

</aside>

문법

  1. 서버액션은 "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() {
  // ...
}
  1. 클라이언트 컴포넌트에서는 오직 모듈레벨 "use server" 를 사용한 서버액션만 불러올수있다.
//클라이언트 컴포넌트는 오직 모듈레벨 서버액션만 불러올 수 있다.
'use client'

import { create } from '@/app/actions'
 
export function Button() {
  return (
    // ...
  )
}
  1. 서버액션은 클라이언트 컴포넌트의 prop 으로 전달 할 수 있다.
<ClientComponent updateItem={updateItem} />
'use client'
 
export default function ClientComponent({ updateItem }) {
  return <form action={updateItem}>{/* ... */}</form>
}

<Form> 태그의 액션(Submit) 을 서버사이드의 서버 액션에서 처리 해보자

  1. Form 태그의 필드를 관리하고 싶을때

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>
}
  1. 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) {
  // ...
}
  1. 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>
  )
}