본문 바로가기
⚡️etc.

[원티드] 프리온보딩 프론트엔드 챌린지 3차 세션 실습

by s2ylvia 2024. 6. 13.

미션 1. next.js 프로젝트 설치

npx create-next-app@latest

 

 

미션 2. “wanted/post” App Router 만들기

//app/wanted/post/page.tsx

export default function Index() {
	return (
    	<div>hello</div>
    )
}

 

 

미션 3. <form> 태그와 <input> 태그를 이용하여 이름/희망연봉 입력폼 만들기
마지막에 “전송"버튼 추가

export default function Index() {
  return (
    <>
      <form>
        <div className="pb-3">
          이름 <input type="text" name="name" />
        </div>
        <div className="pb-3">
          연봉 <input type="number" name="salary" />
        </div>
        <button className="bg-red-500 p-5">전송</button>
      </form>
    </>
  );
}

 

 

미션 4. handleForm 추가 후 form action tag에 연결

  • action : form 태그 안에 action 속성은 form 안에 작성된 내용들을 서버로 보낼때, 해당 내용들이 도착할 URL 주소
  • button 의 디폴트 타입은 "submit"이며,
    form 내부에 버튼이 있으면 자동으로 "submit"이 설정된다.
async function handleForm(formData: FormData) {
  "use server";
  console.log(formData.get("name"), formData.get("salary"));
  console.log("i run in the server");
}

export default function Index() {
  return (
    <>
      <form action={handleForm}>
        <div className="pb-3">
          이름 <input type="text" name="name" />
        </div>
        <div className="pb-3">
          연봉 <input type="number" name="salary" />
        </div>
        <button className="bg-red-500 p-5">전송</button>
      </form>
    </>
  );
}

 

//console
sylvia 9000
i run in the server

 

 

미션 5. 전송 버튼을 눌렀을때 loading으로 text 바꾸기

  • useFormStatus : 마지막 form 제출의 상태 정보를 제공하는 Hook이다.
const { pending, data, method, action } = useFormStatus();

 

  • 반환값
  • pending: true이거나 false값을 갖는다. form이 제출중이라면 true이고 그렇지 않으면 flase이다.
  • data: 상위 form이 제출하는 데이터가 포함된 FormData 인터페이스를 구현하는 개체이다.
  • method: 'get' 또는 'post'의 문자열 값. 이는 상위 form이 GET 또는 POST HTTP 메서드로 제출하는 여부를 나타낸다. 기본적으로 form은 GET 메서드를 사용하며 메서드 속성으로 지정할 수 있다.
  • action: 상위 form의 action prop에 전달된 함수에 대한 참조다. 상위 form이 없으면 null이다. action prop에 URI값이 제공되거나 지정된 action prop이 없으면 status.action은 null이 된다.

//page.tsx

import handleForm from "./action";
import FormBtn from "./form-btn";

export default function Index() {
  return (
    <>
      <form action={handleForm}>
        <div className="pb-3">
          이름 <input type="text" name="name" />
        </div>
        <div className="pb-3">
          연봉 <input type="number" name="salary" />
        </div>
        <FormBtn />
      </form>
    </>
  );
}
//form-btn.tsx

"use client";

import { useFormStatus } from "react-dom";

export default function FormBtn() {
  const { pending } = useFormStatus();
  return (
    <button className="bg-red-500 p-5" disabled={pending}>
      {pending ? "전송 중..." : "전송"}
    </button>
  );
}
//action.ts

"use server";

export default async function handleForm(formData: FormData) {
  await new Promise((resolve) => setTimeout(resolve, 3000));
  console.log(formData.get("name"), formData.get("salary"));
  console.log("i run in the server");
}

 

 

미션 6. 서버에서 유효성 체크 후에 CLIENT로 넘겨주기

  • useFormState: form action의 결과에 따라 state를 최신 상태로 업데이트 할 수 있는 Hook이다.
  • state는 form이 마지막으로 제출되었을 때 액션에 의해 반환된 값이다. 첫번째 렌더링에서는 초기 설정값.
  • formAction은 form에 전달될 action 함수.
const [state, formAction] = useFormState(fn, initialState, permalink?);

//page.tsx

"use client";

import handleForm from "./action";
import FormBtn from "./form-btn";
import { useFormState } from "react-dom";

export default function Index() {
  const [state, action] = useFormState(handleForm, null);
  return (
    <>
      <form action={action}>
        <div className="pb-3">
          이름 <input type="text" name="name" />
          {state?.error.includes("name") && "이름이 틀렸어요"}
        </div>
        <div className="pb-3">
          연봉 <input type="number" name="salary" />
          {state?.error.includes("salary") && "연봉이 틀렸어요"}
        </div>
        <FormBtn />
      </form>
    </>
  );
}
//action.ts

"use server";

export default async function handleForm(prevState: any, formData: FormData) {
  await new Promise((resolve) => setTimeout(resolve, 3000));
  console.log(formData.get("name"), formData.get("salary"));
  console.log("i run in the server");

  //validation
  return {
    error: ["name", "salary"],
  };
}

 

 

 

 

 

 

참고

https://react.dev/reference/react/useActionState

 

useActionState – React

The library for web and native user interfaces

react.dev

https://react.dev/reference/react-dom/hooks/useFormStatus

 

useFormStatus – React

The library for web and native user interfaces

react.dev

https://s2ylvia.tistory.com/manage/newpost/10?type=post&returnURL=https%3A%2F%2Fs2ylvia.tistory.com%2F10

 

Tistory

좀 아는 블로거들의 유용한 이야기

www.tistory.com

https://velog.io/@white0_0/React-useFormStatus

 

[React] useFormStatus

useFormStatus useFormStatus 마지막 form 제출의 상태 정보를 제공하는 Hook이다. 예시 코드 상태 정보를 얻으려면 Submit 컴포넌트가 내에서 렌더링 되어야 합니다. hook은 form이 제출되고 있는지 알려주는 p

velog.io

https://velog.io/@hill0ne/form-%EC%9D%98-submit%EC%9D%B4-%EB%B0%9C%EC%83%9D%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%84-%EB%95%8C-%EB%B6%80%EC%A0%9C-button-type-%EC%9D%98-%EC%B0%A8%EC%9D%B4

 

form 의 submit이 발생되지 않을 때 (부제: button type 의 차이)

todo list를 리펙토링 하면서 input에 keyup 이벤트로 새 글을 추가하는 함수를 실행시키던 것에서form 을 날려서 실행시키는 것으로 개선해 보았다.당연히 될 것으로 생각하고 enter 키를 빡빡 눌렀는

velog.io

https://e-juhee.tistory.com/entry/React-useFormState-useFormStatus

 

[React] useFormState, useFormStatus

form 액션의 결과에 기반하여 상태를 업데이트할 수 있게 해주는 Hook 마지막 양식 제출의 status 정보를 제공하는 Hook 📄 Docs 🔗 useFormState 🔗 useFormStatus useFormState 💡 현재는 Canary와 experimental channe

e-juhee.tistory.com