[React]-Form을 만들어보자!/제어 컴포넌트와 비제어 컴포넌트??

badassong·2023년 4월 10일
0

React

목록 보기
33/56
post-thumbnail

오늘은 form을 만드는 두 가지 방법에 대해 알아보았다.

Controlled Component: 제어 컴포넌트
Uncontrolled Component: 비제어 컴포넌트

사용자가 무언가를 클릭하거나 했을 때 UI가 업데이트 되어야 한다면, React Component 자체 내 상태가 변경되면서 UI가 업데이트 되어야 하는데,

import React, { useState } from "react";

export default function AppForm() {
  
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(form);
  };
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="name">이름:</label>
      <input
        type="text"
        id="name"
        name="name"
      />
      <label htmlFor="email">이메일:</label>
      <input
        type="email"
        id="email"
        name="email"
     />
      <button>Submit</button>
    </form>
  );
}

이렇게 만든 form을 보면 input에 입력을 했을 때 React 내부적으로 상태 변경이 이루어지지 않아도 바로 UI상에서 내가 입력한 것이 보인다.
이런 것을 Uncontrolled Component라고 한다.
이런 경우 React가 추구하는 원칙과 어긋나기 때문에 데이터가 보여질 때 이 컴포넌트에서 가지고 있는 상태와 똑같이 매칭이 되도록 만들어주어야 한다!
이 말인즉슨 Controlled Component로 만들어 줘야 한다는 의미!
그렇게 하려면 무엇을 이용한다? 바로 useState!

import React, { useState } from "react";

export default function AppForm() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const handleSubmit = (e) => {
    e.preventDefault();
  };

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="name">이름:</label>
      <input
        type="text"
        id="name"
        name="name"
        value={name}
        onChange={(e) => {
            setName(e.target.value);
        }}
      />
      <label htmlFor="email">이메일:</label>
      <input
        type="email"
        id="email"
        name="email"
        value={email}
        onChange={(e) => {
          setEmail(e.target.value);
        }}
      />
      <button>Submit</button>
    </form>
  );
}

이렇게 작성하면

이렇게 input에 작성할 때마다 상태가 업데이트 되는 걸 확인할 수 있다.

그런데 여기서!!

이름과 이메일은 사용자에 관한 정보이므로 하나의 객체로 묶어서 상태를 관리해 주면 어떨까?

import React, { useState } from "react";

export default function AppForm() {
  const [form, setForm] = useState({ name: "", email: "" });
  const handleSubmit = (e) => {
    e.preventDefault();
  };
  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm({ ...form, [name]: value });
  };
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="name">이름:</label>
      <input
        type="text"
        id="name"
        name="name"
        value={form.name}
        onChange={handleChange}
      />
      <label htmlFor="email">이메일:</label>
      <input
        type="email"
        id="email"
        name="email"
        value={form.email}
        onChange={handleChange}
      />
      <button>Submit</button>
    </form>
  );
}

handleChange라는 함수를 따로 만들어서 onChange에 걸어줬는데, 이벤트에서 발생하는 target의 name과 value를 받아와서 setForm을 해주는 것이다!

그런데 여기서,

setForm({ ...form, [name]: value });

왜 name을 대괄호로 감싸주는 것인지 궁금해서 찾아보았더니,
객체의 key값이 동적으로 할당될 때는 []형식으로 써주어야 한다고 한다!

++ form에서 submit 버튼을 클릭했을 때 페이지가 refresh 되는 걸 원치 않는다면 꼭 preventDefault 함수를 실행시켜야 한다!!

profile
프론트엔드 대장이 되어보쟈

0개의 댓글