Input 값을 관리하는 함수를 만들고 이 값을 State에 저장해봅시다.


먼저 Input 값을 왜 State로 관리하는지부터 알아봅시다. 예를 들어 사용자가 아이디와 비밀번호를 입력하고 로그인 버튼을 누르는 상황을 가정해봅시다. 만약 여기서 Input 값을 State로 저장하지 않는다면 버튼을 눌렀을 때 어떻게 해야 할까요? handleSubmit 이라는 함수를 만든다고 생각해봅시다. 그럼 그 함수에는 버튼이 눌렸을 때, 아이디와 비밀번호 값을 입력받는 input 태그로부터 값을 전달받아 서버로 전달해야 합니다. 그럼 어떻게 input 태그로부터 값을 받아올까요? React에서는 Ref라는 DOM에 직접적인 접근을 할 수 있게 하는 기능이 있습니다. 이를 통해서 값을 받아올 수 있습니다. 하지만 React 공식 홈페이지에서는 Ref를 남용하지 말라는 글이 있습니다. State로 해결할 수 없는 문제에 대해서만 Ref를 사용하라고 권장하고 있죠. 따라서 대부분은 Input 값을 State로 저장합니다.

데이터를 저장하기 위해서는 그 값을 관리하는 함수가 필요합니다. 따라서 이번 페이지에서는 Input 값을 관리하는 함수를 만들어 프로젝트에 적용해보겠습니다. App 컴포넌트에 handleInput 이라는 함수를 만들고 InputBox 컴포넌트에 Props로 전달하여 Input 태그 내의 값이 변경되었을 때 실행되어 state를 변경하도록 작성해보겠습니다. 먼저, 아래와 같이 App 컴포넌트를 수정해주세요.

import React, { Component } from "react";
import InputBox from "./components/InputBox";
import PhoneList from "./components/PhoneList";
import "./App.css";
import { dummyData } from "./lib/dummyData.js";

class App extends Component {
  state = {
    dummyData,
    name: "",
    phone: ""
  };

  handleInput = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  render() {
    const { handleInput } = this;
    const { dummyData, name, phone } = this.state;

    return (
      <div className="container">
        <InputBox
          name={name}
          phone={phone}
          onChange={handleInput}
        />
        <PhoneList list={dummyData} />
      </div>
    );
  }
}

export default App;

우선 state에 name과 phone 값을 추가해주었습니다. 그리고 handleInput이라는 함수를 만들어 이를 InputBox 컴포넌트에 Props로 전달해주었습니다. 여기서 handleInput 함수를 살펴봅시다.

handleInput = e => {
  this.setState({
    [e.target.name]: e.target.value
  });
};

이 코드는 어떻게 동작하는 걸까요? 우선 이 코드를 해석하기 전에 자바스크립트 Event 객체에 대해 알아야 합니다. 이벤트 객체란 DOM과 관련된 이벤트가 발생했을 때, 관련 정보를 저장하는 객체를 말합니다. 예시로 버튼이 눌렸을 때, input 값이 변경되었을 때 등이 있죠. 브라우저에서는 이벤트 핸들러 함수에 Event 객체를 매개변수로 전달합니다. 위의 코드에서 이벤트 핸들러 함수는 handleInput 함수입니다. onChange라는 이벤트가 발생했을 때 실행되도록 할 것이기 때문입니다. 여기서 이벤트 객체를 콘솔에 출력해보면 아래와 같이 나올 것입니다.

SyntheticEvent {dispatchConfig: {…}, _targetInst: FiberNode, nativeEvent: InputEvent, type: "change", target: input.InputBox_input_box_input__22cgj, …}

이런 식으로 이벤트 변경 사항이 다 기록되는 것입니다. 그럼 이 중에서 target이라는 key 값을 가진 부분을 봅시다. e.target은 해당 이벤트가 발생한 element를 가리킵니다. 이 정도만 알아도 handleInput 함수를 충분히 이해할 수 있습니다. e.target.name은 이벤트가 발생한 Element의 name 속성값을 가져오는 것이고, e.target.value는 이벤트가 발생한 Element의 value 속성값을 가져오는 것이죠. 저희는 InputBox 컴포넌트에 들어있는 2개의 Input 태그의 name 속성값을 각각 name, phone 으로 지정했습니다. 그럼 만약 name 속성값으로 phone을 가지는 input 태그에 0을 입력한다면 handleInput 함수에서 this.setState({ phone: "0" }); 이 실행되죠. 위와 같은 이유로 state에서도 key 값을 name과 phone으로 설정해놨습니다. 그럼 이 함수를 InputBox에 전달해보도록 합시다.