본문 바로가기
C.W.K.
Stream
Lesson 03 of 06 · published

useFormStatus — prop-drilling 없는 대기

~11 min · useformstatus, react-19, actions

Level 0React 입문자
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
Submit 버튼은 자신을 감싼 form이 제출 중인지 알아야 해. useFormStatus를 쓰면 부모가 대기 상태를 일일이 내려주지 않아도 돼.

기본 모양

const { pending, data, method, action } = useFormStatus()를 form 안에서 렌더링되는 자식 컴포넌트에 호출해. 가장 자주 쓰는 값은 제출이 진행 중인지 알려 주는 pending이야.

가장 가까운 form을 읽는다

useFormStatus는 컴포넌트를 감싸는 가장 가까운 form의 상태를 읽어. form의 자식이 아닌 곳이나 form을 렌더링하는 부모에서 호출하면 실제 제출 상태가 아니라 기본값을 받게 돼.

prop drilling 없이 제출 버튼 만들기

이 훅이 없으면 부모가 isPending을 읽어 SubmitButton에 prop으로 내려줘야 해. useFormStatus를 쓰면 버튼이 자기가 속한 form의 상태를 직접 읽으므로 다른 form으로 옮겨도 연결이 유지돼.

제출 중인 데이터 보기

data에는 진행 중인 제출의 FormData가 들어 있어. 저장 중인 제목을 미리 보여 주는 것처럼 제출 내용을 낙관적으로 표시할 수 있고, 다음 레슨의 useOptimistic와 자연스럽게 이어져.

대기 UI를 기다리는 작업 가까이에 둬. 버튼은 자기 spinner를, input은 자기 disabled 상태를 form context에서 직접 읽게 해. 중앙의 거대한 isPending 상태와 prop drilling을 만들 필요가 없어.

현재 form의 제출 정보를 읽어

useFormStatus는 pending뿐 아니라 제출 중인 FormData와 method, action 정보를 제공해. 그래서 재사용 SubmitButton이 prop 없이 현재 form을 disable하고, 별도 PendingPreview가 지금 제출하는 값을 보여 줄 수 있어.

반드시 form의 자식에서 호출해

훅을 호출하는 컴포넌트가 form 바깥에 있거나 같은 컴포넌트가 만든 form보다 위에 있으면 그 제출 상태를 읽지 못해. 함수 Action이 아닌 문자열 action을 쓰는 네이티브 form에서도 React Action lifecycle이 없으므로 기본 상태만 돌아와.

Code

자기 form 상태를 읽는 재사용 SubmitButton·tsx
import { useFormStatus } from "react-dom";

export function SubmitButton({ children, className = "" }: { children: React.ReactNode; className?: string }) {
  const { pending } = useFormStatus();
  return (
    <button
      type="submit"
      disabled={pending}
      className={`px-4 py-2 bg-brand text-bg rounded disabled:opacity-50 ${className}`}
    >
      {pending ? "Saving…" : children}
    </button>
  );
}

// 어떤 form 안에서든 사용 — prop 필요 없음.
// <form action={saveDraft}><input name="title" /><SubmitButton>Save</SubmitButton></form>
제출 중인 데이터 미리 보기·tsx
import { useFormStatus } from "react-dom";

function PendingPreview() {
  const { pending, data } = useFormStatus();
  if (!pending || !data) return null;
  const title = data.get("title") as string;
  return (
    <p className="text-muted text-sm italic">
      Saving title: {title}…
    </p>
  );
}

// <PendingPreview />를 form 안에 두면 제출이 진행되는 동안만
// 나타나고 현재 제출한 값을 보여 줘.

External links

Exercise

Lesson 2의 구독 form을 고쳐 SubmitButton이 useFormStatus로 자기 pending 상태를 읽게 해. 부모가 넘기던 disabled prop을 제거한 뒤 제출 중에도 버튼이 비활성화되는지 확인해. 이어서 data에서 제출 중인 이메일을 읽는 PendingPreview를 form 안에 추가해.
Hint
SubmitButton과 PendingPreview를 각각 form의 자식 컴포넌트로 만들어. 같은 컴포넌트에서 form을 만들고 그 위에서 훅을 호출하면 그 form의 상태를 읽을 수 없어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.