본문 바로가기

JavaScript/React

6. 이벤트 처리

React 이벤트 처리

React의 이벤트 처리방식은 Vanila JS의 이벤트 처리 방식과 거의 유사하다.

 

몇 가지 차이만 알고 있으면 된다.

 

차이 1] 기본 문법

  1. React 이벤트는 소문자 대신 카멜 표기법(camelCase)를 사용한다
  1. JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달한다

 

HTML에서 작성

<button onclick="activateLasers()"> Active Lasers </button>

React에서 작성

<button onClick={activeLasers}> Activate Lasers </button>

이벤트 onclick대신 onClick으로.. 마치 낙타(camel) 혹 처럼 쓴다. " " 문자열 대신 { } 을 사용하여 JSX로 전달한다.

 

 

 

차이 2] 이벤트 기본 동작 방지

React는 false를 반환해도 기본 동작을 방지할 수 없다. 반드시 preventDefault를 호출해야한다.

 

비교를 위해 새 페이지를 여는 기본 동작을 막는 코드를 작성해보자.

 

HTML에서 작성

<a href="#" onclick="console.log('The link was clicked.'); return false">
	Click me
</a>

React에서 작성

function ActionLink(){
	function handleClick(e){
		e.preventDefault();
		console.log('The link was clicked.');
	}

	return(
		<a href="#" onClck={handleClick}>
			Click me
		</a>
	);
}

HTML 태그 내에 작성한 코드는 false값을 반환해서 태그 기능이 동작 않토록 했으나 React는 그렇게 쓸 수 없다. 그래서 handleClick 함수 안에 preventDefault()를 정의해서 쓰도록 했다.

 

위 코드는 이벤트 기본동작은 하지 않고, console.log('The link was clicked.')만 찍힌다.

 

 

차이 3] 이벤트에서의 this

기본적으로 onClick등으로 전달한 이벤트에서 this를 호출한 경우 바인딩 되어있지 않기 때문에 undefined로 표시된다. ( 쉽게 말해 컴퓨터 입장에서 this가 누굴 가르키는지 알 수 없을 때 "이거다!" 알려주는 개념)

 

자바스크립트에서의 바인딩(javascript Binding) 참고

React 바인딩(이벤트/메서드 연결)
https://jeong-pro.tistory.com/79

 

 

리액트 또한 onClick=처럼 뒤에 ()를 사용하지 않고 메서드를 참조할 경우, 해당 메서드를 바인딩 해줘야 한다. 공홈에 예제 이해가 잘 안 돼서.. 다른 예제를 만들어봤다

 

 

클릭할 때 마다 글자가 바뀌는 버튼을 하나 만들어보자.

class ButtonBind extends React.Component {
     constructor(props) {
        super(props);
        this.state = { toggle: false };
        this.toggleButton = this.toggleButton.bind(this);
     }

     toggleButton() {
        this.setState(state => ({
           toggle: !state.toggle
        }));
				console.log(this);
     }

     render() {
        return (
           <div>
              <button onClick={this.toggleButton}>
                 {this.state.toggle ? "ON" : "OFF"};
              </button>
           </div>
        );
     };
  };


ReactDOM.render(<div><ButtonBind /></div>, document.querySelector('#root'));

constructor에서 toggle을 false 초기 값으로 셋팅한다. 그리고 toggleButton 함수를 onClick 처리 함수로 추가해서 버튼이 클릭 될 때 마다 호출되도록 한다. 마지막으로 toggleButton 함수를 만들고 불릴 때 마다 toggle 스위치를 껐다켰다 하도록 한다.

 

그러면 'setState' of undefined라는 에러가 발생한다. onClick이 toggleButton 함수를 호출 할 때 this가 선언되지 않아서 발생하는 문제이다.

🤔
toggleButton() 메서드의 this는 어디일까?
window나 undefined가 되어버린다.
window나 undefined에는 setState 메소드가 없기 때문에 this.setState 호출 시 에러가 발생한다.
이렇게 this.toggleButton = this.toggleButton.bind(this); 바인딩 해주면
this는 ButtonBind 클래스를 가르키게 된다.

* render()와 toggleButton()의 this의 차이는 생명주기를 살펴보면 더 명확하다 5. State와 생명주기

 

제로초님의 글 덕분에 더 잘 이해할 수 있었다..

(React) 컴포넌트 이벤트 연결(바인딩)

 

이건 React만의 특수한 동작이 아니다. JavaScript에서 함수가 작동하는 방식이다. 일반적으로 onClick=과 같이 뒤에 ()를 사용하지 않고 메서드를 참조 할 경우, 해당 메서드를 바인딩 해야 한다고... ( 분명 본 적 있는데 제대로 이해하지 않고 넘어가니, 리액트 공부하면서 더 끙끙거린 것 같다 )

 

 

.bind(this)를 꼭 써야할까?

봤다시피.. .bind(this) 코드를 작성하면 코드가 지저분해지고, 코드량도 늘어난다. 신경도 써줘야하니 귀찮다. 그래서 이를 해결 할 수 있는 방법 2가지가 있다.

 

  1. 클래스 필드 문법 사용
class LoggingButton extends React.Component {
  // 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
  // 주의: 이 문법은 *실험적인* 문법입니다.
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

console.log창에 LogginButton이 찍힘. this가 클래스 내에서 작동하는 것을 볼 수 있다.

this가 handleClick 내에서 바인딩 되도록 해주는 방법이다. 공홈에도 나와있듯이 실험적 문법이어서 bable을 설정해줘야한다.

 

뭐가 다른지 한참 찾았다; ButtonBind의 예시로 따지자면

toggleButton = () => {
    this.setState(state => ({
       toggle: !state.toggle
    }));
    console.log(this);
 }

이렇게 바꿔준거다.

 

 

2. 콜백에 화살표 함수 사용하기

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
    return (
      <button onClick={() => this.handleClick()}>
        Click me
      </button>
    );
  }
}

이렇게 콜백 함수를 사용할 수도 있다. 이 문법의 문제점은 LogginButton이 렌더링 될 때 마다 다른 콜백이 생성된다는 것이다.

 

이 방법은 추천 안함!

 

 

 

bind하거나 () ⇒ {} 문법을 사용하면 좋다. 나는 나는 클래스 필드 문법을 많이 사용할 듯 하다.

 

 

반응형

'JavaScript > React' 카테고리의 다른 글

create-react-app  (0) 2021.03.08
리액트 시작하기-기본적으로 필요한 툴  (0) 2021.03.08
11. 합성 vs 상속  (0) 2021.02.05
5.1 State 올바르게 사용하기  (0) 2021.02.01
5. State와 생명주기  (0) 2021.02.01