노트

useActionState와 폼 액션

useActionState

프런트엔드#react · 연결된 개념 6개

쉽게 말하면

useActionState는 폼을 제출했을 때 '처리 중'인지와 마지막 결과를 한 번에 챙겨 주는 훅이에요. 접수 창구에 서류를 내면 처리 중 표시가 켜지고 결과 쪽지가 돌아오는 것과 비슷해서, 로딩 플래그를 따로 안 짜도 돼요.

비유가 깨지는 곳 창구 앞에서 멍하니 기다리는 것과 달리 액션은 transition 안에서 실행돼요. 서버 액션과 함께 쓰면 JS가 로드되기 전에도 폼이 제출돼요. 액션은 이전 상태와 FormData를 받아 다음 상태를 돌려줘요.

React 19에서는 <form action={함수}>에 함수를 바로 넘길 수 있고, useActionState가 그 액션의 대기 상태와 마지막 결과를 한 훅으로 관리한다. useState + onSubmit + 로딩 플래그로 짜던 패턴을 대체한다.

'use client'
const [state, formAction, isPending] = useActionState(updateName, null)
// updateName(prevState, formData) — 서버 함수여도 된다
 
<form action={formAction}>
  <input name="name" disabled={isPending} />
  <button disabled={isPending}>저장</button>
  {state?.error && <p>{state.error}</p>}
</form>
  • 액션은 이전 상태와 FormData를 받아 다음 상태(에러 메시지, 결과)를 반환한다. 서버 쪽 검증 결과를 그대로 화면에 보여 주기 좋다(서버 함수와 서버 액션)
  • form action으로 넘긴 함수는 자동으로 transition 안에서 실행된다(useTransition)
  • 점진적 향상(Progressive Enhancement): 서버 액션과 함께 쓰면 JS(JavaScript)가 로드되기 전에도 폼이 제출되고, 하이드레이션 전 제출은 나중에 다시 실행된다(하이드레이션)
  • useFormStatus: 폼 안쪽의 자식 컴포넌트(제출 버튼)가 props를 받지 않고도 상위 폼의 제출 상태를 읽는다
  • useOptimistic: 서버 확정 전에 결과를 미리 화면에 반영하고, 실패하면 되돌린다

입력값을 state로 들지 않는 비제어 입력과 잘 맞는다. 같은 일을 클라이언트 캐시 쪽에서 하는 방법은 TanStack Query의 useMutation이다.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 상태 패턴

    객체의 행동이 현재 상태에 따라 달라질 때, 상태마다 별도 객체를 두고 현재 상태 객체에 행동을 맡기는 패턴. 상태별 조건문이 메서드마다 반복되는 문제를 푼다.

  • React 상태 갱신

    React는 상태를 직접 고치지 않고 새 값을 setState로 넘겨야 다시 그린다. 이전 값과 Object.is로 비교하므로, 같은 객체를 고친 뒤 넘기면 바뀐 줄 모른다.

  • useReducer

    useReducer는 "이전 상태와 액션을 받아 새 상태를 돌려주는" 리듀서(Reducer) 함수로 상태를 관리하는 훅이다. 이름처럼 Array.prototype.reduce의 아이디어를 시간축으로 늘린 것이다. 배열 요소 대신 시간순으로 들어오는 액션을 누적한다.

  • Redux 이후의 상태 관리 선택

    한때 React 앱의 기본값이던 Redux는 2025~2026년 기준으로 여러 선택지 중 하나가 됐다. 상태를 종류별로 나눠 각자에 맞는 도구를 고르는 방식이 자리 잡았기 때문이다.

  • Activity와 숨겨진 라우트 보존

    Activity는 React 19.2의 컴포넌트로, UI를 언마운트하지 않고 display: none으로 숨기면서 state와 DOM(Document Object Model)을 보존한다. 숨기는 동안 Effect는 정리(cleanup)된다. 예전 이름은 Offscreen이다.

보기 옵션