본문 바로가기
Front-end/React

React에서 폼 form을 다루는 방법

by softserve 2023. 5. 25.
반응형

1. 참조를 이용하는 방법

 

useRef() 훅은 컴포넌트 생명주기 동안 사용할 수 있는 ref 객체를 반환해 줍니다.

이 객체는 current 프로퍼티에 렌더링에 필요하지 않은 값을 저장해 두고, 필요할 때마다 참조할 수 있도록 해줍니다.

CreateForm.js는 아이디와 패스워드를 저장할 수 있는 ref 객체(loginId, password)를 <input> 엘리먼트의 ref 속성에 추가해주고 있습니다. submit 이벤트가 발생하면 ref 객체의 current.value에 있는 값을 id, pw에 각각 저장한 다음 onAccess 함수를 통해서 상위 컴포넌트로 올려 보내고 다시 초기화시켜 줍니다. 만약 입력한 아이디를 유지하고 싶으면 loginId.current.value = ""; 부분을 삭제하면 됩니다.

이 부분은 DOM 노드의 값을 직접 변경해 주는 명령형 코드입니다. 이렇게 DOM 그 자체를 통해서 폼의 값을 다루고 있으므로  CreateForm은 제어되지 않는 컴포넌트(uncontrolled component)입니다. 반대로 제어 가능한 컴포넌트의 경우 리액트 컴포넌트를 통해서 폼 데이터를 핸들링할 수 있습니다. 일반적으로는 제어 가능한 컴포넌트의 사용이 권장되나, 리액트 밖에서 폼에 접근해야 하는 경우 제어되지 않는 컴포넌트를 사용할 수 있습니다.

참조를 이용해서 아이디와 비밀번호로 간단히 회원가입을 할 수 있는 폼을 만들어보도록 하겠습니다.

<CreateForm.js>

import React, { useRef } from "react";

export default function CreateForm({ onAccess = f => f }){
    const loginId = useRef();
    const password = useRef();

    const submit = e => {
        e.preventDefault(); 
        const id = loginId.current.value;
        const pw = password.current.value;
        onAccess(id, pw);
        loginId.current.value = "";
        password.current.value = "";
    };

    return (
        <form onSubmit={submit}>
            <input ref={loginId} type="text" required/>
            <input ref={password} type="password" required/>
            <button>submit</button>
        </form>
    );
}

CreateForm의 부모 컴포넌트인 App.js에서는 입력된 id, pw를 전달받아 화면에 보여주고 있습니다.

<App.js>

import './App.css';
import {useState} from 'react';
import CreateForm from './CreateForm';
 
export default function App() {
  return (
      <CreateForm
        onAccess={(id, pw) => alert(id + ":" + pw)}
      />
  );
}

 

2. 상태를 통해서 폼 처리하기

 

useState()를 사용해서 상태를 관리하는 부분을 추가했습니다. 전체적인 구조는 비슷하지만  여기서는 <input>value 프로퍼티에 상태변수인 loginId, password를 넣어주고 있습니다.

<CreateForm.js>

import React, { useState } from "react";

export default function CreateForm({ onAccess = f => f }){

    const [loginId, setLoginId] = useState("");
    const [password, setPassword] = useState("");

    const submit = e => {
        e.preventDefault(); 
        onAccess(loginId, password);
        setLoginId("");
        setPassword("");
    };

    return (
        <form onSubmit={submit}>
            <input 
                value={loginId}
                onChange={e => setLoginId(e.target.value)}
                type="text"
                required
            />
            <input 
                value={password} 
                onChange={e => setPassword(e.target.value)}
                type="password"
                required
            />
            <button>submit</button>
        </form>
    );
}

 

이 경우는 리액트가 폼의 상태를 제어하게 됩니다. 주의해야 할 점은 사용자가 글자 하나를 입력할 때마다 렌더링이 이루어지기 때문에 이 컴포넌트 내에서 복잡한 연산을 수행할 경우 문제가 될 수 있다는 점입니다.

 

3. <input>이 엄청나게 많은 경우

 

<input>에는 valueonChange 프로퍼티가 공통적으로 들어가고 있습니다. 지금이야 2개뿐이지만 공공기관에 어떤 신청서 같은 것을 작성해 제출해야 할 경우 수 십 개의 <input>이 필요하게 됩니다. 그리고 중복되는 부분을 수십 번 붙여 넣기 해야 합니다. 커스텀 훅을 만들어서 이 부분을 보다 깔끔하게 만들어줄 수 있습니다.

useInput.js는 내부적으로 상태 value를 관리하고 있습니다.

useInput() 훅이 반환하는 것은 첫 번째 원소인 valueonChange 프로퍼티, 그리고 두 번째 원소로 값을 init으로 초기화해 주는 함수입니다.

<useInput.js>

import { useState } from "react";

export const useInput = init => {
    const [value, setValue] = useState(init);
    return [
        {value, onChange: e => setValue(e.target.value)},
        () => setValue(init)
    ];
}

위에서 작성한 소스를 아래와 같이 useInput()을 이용하도록 바꿔줍니다.

<CreateForm.js>

import React, { useRef, useState} from "react";
import { useInput } from "./useInput.js";

export default function CreateForm({ onAccess = f => f }){

    const [idProps, resetId] = useInput("");
    const [pwProps, resetPw] = useInput("");

    const submit = e => {
        e.preventDefault();
        onAccess(idProps.value, pwProps.value);
        resetId();
        resetPw();
    };

    return (
        <form onSubmit={submit}>
            <input
                {...idProps}
                type="text"
                required
            />
            <input
                {...pwProps}
                type="password"
                required
            />
            <button>submit</button>
        </form>
    );
}

 

valueonChange 프로퍼티를 구조 분해해서 다수의 <input>에 넣어줍니다.

그리고 submit에서 초기화를 할 때는 resetId, resetPw 함수를 사용합니다.

 

4. 폼으로 입력받은 값을 상태로 저장하기

 

앞서 App.js 에서는 입력된 값을 경고창을 통해 확인해주기만 했습니다. 이제 입력된 아이디와 비밀번호를 users 상태에 추가해 주겠습니다. 초기값은 user-data.json에 저장된 내용입니다. 

<App.js>

import React, {useState} from 'react';
import CreateForm from './CreateForm';
import userData from './user-data.json';
 
export default function App() {
  const [users, setUsers] = useState(userData);
  return (
      <CreateForm
        onAccess={(id, pw) => {
          const newUsers = [
            ...users,
            {
              date: "230525",
              id,
              pw
            }
          ];
          setUsers(newUsers);
        }}
      />
  );
}

 

 

 

 

 

 

 

참고

러닝리액트 2판 - O'REILLY

 

반응형

'Front-end > React' 카테고리의 다른 글

React 시작하기  (2) 2022.09.20

댓글