본문 바로가기
react

useFormState hook으로 Form 상태를 다루자

by cactuslog 2024. 3. 10.

 

useFormState란?

form action의 결과를 기반으로 state를 업데이트 할 수 있도록 제공하는 hook이다.

 


 

useFormState의 parameter와 returns에 대해 알아보자

const [state, formAction] = useFormState(fn, initialState, permalink?);

 

Parameter

fn

1. form이 submit 되었을 때 호출되는 함수

 

2. 이전 state와 FormData를 argument로 받는다.

async function increment(previousState: number, formData: FormData) {
  return previousState + 1;
}

 

initialState

초기값

 

permalink (optional)

1. form이 수정하는 고유한 page url을 포함하는 문자열이다.

 

2. fn이 서버 액션이고 form이 자바스크립트 bundle이 로드되기 전에 제출된다면 브라우저는 현재 페이지의 url이 아닌permalink로 이동한다.

 

3. form이 hydrate 된 후에 이 파라미터는 효과가 없다.

 


returns

state

1. 현재 값이다.

 

2. 첫렌더링 시에는 initialState로 넘긴 값이랑 일치하고 action이 실행된 후에는 action에서 반환한 값과 일치한다.

 

formAction

form 컴포넌트의 action prop 또는 button의 formAction prop으로 넘길 수 있는 새로운 action이다.

<form action={action}>

또는

<button type="submit" formAction={action}>submit</button>

 

 


 

form action 후에 변경된 state를 사용하는 예시를 보자

 

 

action-action.ts

"use server";

export async function loginAction(previousState: string, formData: FormData) {
  console.log(`prevState: ${previousState}`);
  console.log(`formData: ${formData}`);

  return "success";
}

 

서버에서 실행되는 action이며 action 후 "success" 문자열을 반환한다.

 

 

form-page.ts

"use client";

import { useFormState } from "react-dom";
import { loginAction } from "@/components/actions/login-action";

export default function Home() {
  const [state, formAction] = useFormState(loginAction, "ready");

  return (
    <main className="h-screen p-20">
      <div className="flex items-center justify-center">
        <form className="flex flex-col space-y-3" action={formAction}>
          <input
            className="border-cyan-500 border-2 rounded-md px-2 py-1"
            type="text"
            name="email"
            placeholder="email"
          />
          <input
            className="border-cyan-500 border-2 rounded-md px-2 py-1"
            type="text"
            name="password"
            placeholder="password"
          />
          <button
            className="px-4 py-2 rounded-md bg-rose-400 text-white"
            type="submit"
          >
            submit
          </button>
        </form>
      </div>
      {state !== "ready" && (
        <p className="text-center my-2 text-green-500 text-lg">{state}</p>
      )}
    </main>
  );
}

 

초기값을 "ready"로 설정하였고 form action 후에 state가 ready가 아닐 경우만 마지막줄에 표시되도록 하였다.

 

form action이 정상적으로 처리되었다면 state가 "success"로 변경되어야 한다.

 

 

 

서버 console 값

prevState: ready
formData: [object FormData]