Form 컴포넌트

<Form> 컴포넌트: 폼 제출을 액션으로 보내기

Remix의 <Form>은 HTML <form>을 점진적으로 향상시킨 컴포넌트예요. 데이터를 fetch로 액션에 제출하면서 useNavigation의 pending 상태를 활성화해, 기본 HTML 폼으로는 어려웠던 고급 UI를 만들 수 있게 해주죠. 폼의 액션이 끝나면 페이지의 모든 데이터가 서버에서 자동으로 다시 검증돼, UI가 데이터와 계속 일치하도록 유지돼요.

HTML 폼 API를 그대로 쓰기 때문에 JavaScript가 로드되기 전에도 서버 렌더링된 페이지가 기본 수준에서는 바로 상호작용해요. Remix가 제출을 관리하기 전에는 브라우저가 제출과 pending 상태(돌아가는 파비콘 같은)를 관리하고, JavaScript가 로드된 뒤부터는 Remix가 그 역할을 넘겨받아 웹 앱 수준의 사용자 경험을 열어줘요.

출처: Remix 공식 문서 — <Form>

본문

<Form>은 URL을 바꾸거나 브라우저 히스토리 스택에 항목을 추가해야 하는 제출에 가장 유용해요. 히스토리 스택을 건드리지 않아도 되는 폼이라면 <fetcher.Form>을 쓰는 게 더 어울려요.

import { Form } from "@remix-run/react";

function NewEvent() {
  return (
    <Form action="/events" method="post">
      <input name="title" type="text" />
      <input name="description" type="text" />
    </Form>
  );
}

Props

action

폼 데이터를 제출할 URL이에요. undefined로 두면 컨텍스트에서 가장 가까운 라우트가 기본값이 돼요. 부모 라우트가 <Form>을 렌더링하는데 URL이 더 깊은 자식 라우트와 일치하면, 그 폼은 부모 라우트로 전송돼요. 반대로 자식 라우트 안의 폼은 자식 라우트로 전송되죠. 항상 전체 URL을 가리키는 네이티브 <form>과는 다른 동작이에요.

method

사용할 HTTP 동사를 정해요: DELETE, GET, PATCH, POST, PUT. 기본값은 GET이에요.

<Form method="post" />

네이티브 <form>GETPOST만 지원하므로, 점진적 향상을 지원하려면 다른 동사는 피하는 게 좋아요.

encType

폼 제출에 사용할 인코딩 타입이에요.

<Form encType="multipart/form-data" />

기본값은 application/x-www-form-urlencoded이고, 파일 업로드에는 multipart/form-data를 써요.

navigate

<Form navigate={false}>로 지정하면 내비게이션을 건너뛰고 내부적으로 fetcher를 사용할 수 있어요. 결과 데이터에는 신경 쓰지 않고 제출만 시작해서 useFetchers()로 pending 상태에 접근하고 싶을 때, useFetcher() + <fetcher.Form>의 축약형이에요.

<Form method="post" navigate={false} />

fetcherKey

내비게이션하지 않는 Form을 쓸 때, 사용할 fetcher key를 직접 지정할 수 있어요.

<Form method="post" navigate={false} fetcherKey="my-key" />

preventScrollReset

<ScrollRestoration>을 쓰고 있다면, 폼 제출 시 스크롤 위치가 창 맨 위로 초기화되는 걸 막아줘요.

<Form preventScrollReset />

replace

새 항목을 히스토리 스택에 push하는 대신 현재 항목을 교체해요.

<Form replace />

reloadDocument

true로 두면 클라이언트 사이드 라우팅 대신 브라우저로 폼을 제출해요. 네이티브 <form>과 같아요.

<Form reloadDocument />

action prop을 생략하면 <Form><form>이 현재 URL에 따라 다른 액션을 호출할 수 있으므로, <form>보다 이 방식(<Form>)을 권장해요. <form>은 현재 URL을 기본값으로 쓰지만 <Form>은 폼이 렌더링된 라우트의 URL을 쓰기 때문이에요.

viewTransition

viewTransition prop은 document.startViewTransition()으로 최종 상태 업데이트를 감싸 이 내비게이션에 View Transition을 활성화해요. 이 view transition에 특정 스타일을 적용해야 한다면 useViewTransitionState()도 함께 써야 해요.

메모

?index

인덱스 라우트와 부모 라우트는 같은 URL을 공유하므로, 둘을 구분하기 위해 ?index 파라미터를 써요.

<Form action="/accounts?index" method="post" />
action url route action
/accounts?index app/routes/accounts._index.tsx
/accounts app/routes/accounts.tsx

더 알아보기