React User Input (이벤트 핸들러, 진실의 원천, this)

Minjae Kwon·2021년 2월 22일
0
post-thumbnail

리액트에서 User Input 과 관련해 마주칠 수 있는 기본 이슈들에 대한 정리이다.

💡 이벤트 관련 special Property names 3종

각각의 이벤트 상황에 맞게 아래 스페셜 속성을 사용한다.

  • onClick: 유저가 클릭했을 때
  • onSubmit: 유저가 폼 제출했을 때
  • onChange: 유저가 인풋창에 텍스트 변경했을 때
// onChange에 이벤트 핸들러를 콜백함수로 할당
class SearchBar extends React.Component {
  onInputChange(e) {
    console.log(e.target.value)
  }

  render() {
    return (
      <div className="ui segment">
        <input type="text" onChange={this.onInputChange} />
      </div>
    );
  }
}

export default SearchBar;
  • 이벤트 핸들러 함수 네이밍 컨벤션:
    "on/handle" + "엘리먼트" + "이벤트"
    (e.g. onFormSubmit, handleFormSubmit )

간단한 이벤트 핸들러의 경우, 아래와 같이 화살표 함수로 처리해도 무방하다.

// inline 화살표 함수로 할당
class SearchBar extends React.Component {
  render() {
    return (
      <div className="ui segment">
        <input type="text" onChange={(e) => console.log(e.target.value)} />
      </div>
    );
  }
}

export default SearchBar;

💡 Controlled element VS Uncontrolled element

위의 이벤트핸들러 설명에서 input 예시는 'uncontrolled element'의 예시이다. 'controlled element' 의 형태로 리팩토링하면 아래와 같다.

import React from "react";

class SearchBar extends React.Component {
  state = { term: "" };

  render() {
    return (
      <div className="ui segment">
        <input
          type="text"
          value={this.state.term}
          onChange={(e) => this.setState({ term: e.target.value })}
        />
      </div>
    );
  }
}

export default SearchBar;

리액트 개발자로서 항상 controlled element 작성을 유념해두어야한다. controlled, uncontrolled element 는 무슨 차이를 바탕으로 할까? 바로 Single source of truth, 즉 진실(데이터)의 원천이 어디에 있느냐 하는 것이다.

리팩토링 전에는 어떤 랜덤한 순간에 input 값을 알고자 할때, 항상 html 에서 정보를 가져와야 했다. 리액트는 유저가 input에 정보를 넣는 순간과 콜백이 일어날때만 정보에 접근이 가능했다.

리팩토링 후에는 모든 진실의 원천을 리액트 컴포넌트에서 통제하게 된다. 더 이상 정보가 돔에서 관리되지 않는다. (다른 프레임워크는 다를 수 있지만, 리액트 공식문서에서 권장하는 single source of truth 관리 방법은 이와 같다.)

controlled element 가 되면, 돔 조작없이 UI 가공도 수월하다. 아래는 그 예시이다.

// placeholder 를 넣고 싶을 때
state = { term: "이메일을 입력해주세요." };

// 모든 input 값을 대문자로 처리하고자 할 때
onChange={(e) => this.setState({ term: e.target.value.toUpperCase() })}

💡 form 이벤트 핸들러에서 preventDefault() 의 역할

이벤트 핸들러에서 아래와 같이 preventDefault 함수를 본 적이 종종 있을 것이다. 브라우저가 가지는 default 동작을 막는 메소드이다.

html에서 특수한 성격을 갖는 엘리먼트들이 있는데 대표적으로 form 이 그렇다. form 에 있는 인풋에 유저가 정보를 입력하고 엔터를 치면, 브라우저는 디폴트 동작으로 정보를 백엔드 서버에 보내고 페이지를 새로고침한다. 이 동작을 원하지 않을 경우, e.prevetDefault 를 통해서 제어할 수 있다.

// 간략화 예시
  onFormSubmit(e) {
    e.preventDefault();
  }

  render() {
    return (
        <form onSubmit={this.onFormSubmit} >
            <input type="text" />
        </form>
      </div>
    );
  }

💡Cannot read property 'state' of undefined

리액트 클래스 컴포넌트에서 this 가 제대로 설정되어 있지 않을 때 마주치는 문구이다. 위의 onFormSubmit 을 예시로, this 를 설정하는 세 가지 방법을 정리해본다.

1번 this 바인딩의 경우 레거시 코드에서 많이 볼 수 있으며, ES2015 의 화살표 함수 도입 후에는 2, 3번을 흔히 볼 수 있다.

1. constructor 내에서 bind 로 정의해주기

constructor() {
  this.onFormSubmit = this.onFormSubmit.bind(this)
}

onFormSubmit(e) {
  e.preventDefault();
}

render() {
  return (
      <form onSubmit={this.onFormSubmit} >
          <input type="text" />
      </form>
    </div>
  );
}

2. 화살표 함수로 바꾸기

onFormSubmit = (e) => {
  e.preventDefault();
}

render() {
  return (
      <form onSubmit={this.onFormSubmit} >
          <input type="text" />
      </form>
    </div>
  );
}

3. jsx 상에서 inline 화살표 함수로 바꾸기

onFormSubmit(e) {
  e.preventDefault();
}

render() {
  return (
      <form onSubmit={(e) => this.onFormSubmit(e)} >
          <input type="text" />
      </form>
    </div>
  );
}
profile
Front-end Developer. 자바스크립트 파헤치기에 주력하고 있습니다 🌴

0개의 댓글