본문 바로가기
02_STUDY/React

[ React ] 클래스 컴포넌트와 함수형 컴포넌트의 이벤트 핸들러 비교

by zestlumen 2023. 8. 28.

이번에는 바인딩이 필요한 클래스 컴포넌트의 이벤트 핸들러를 다루는 방식,

바인딩 없이 클래스 필드 문법을 사용해 클래스 컴포넌트를 사용하는 방식,

현재 널리 쓰이는 함수형 컴포넌트의 이벤트 핸들러를 다루는 방식에 대해서 알아보자.

 

클래스 컴포넌트의 이벤트 핸들러

클래스 컴포넌트는 이벤트 핸들러를 정의하고 사용할 때, 반드시 bind() 메서드를 사용해야 한다.

bind()메서드를 사용해서 이벤트 핸들러와 컴포넌트 인스턴스를 바인딩 해줘야 하는 이유는

클래스 컴포넌트 내부에서 함수가 호출될 때 함수 내부의 this는 컴포넌트 자체를 가리키지 않기 때문이다.

컴포넌트 인스턴스가 아니라 엘리먼트를 가리키게 될 수 있다는 것이다.

 

import React from 'react';

export default class ClassComponent extends React.Component{
	constructor(props) {
    	super(props);
        
        this.state = { count: 0 };
        
        //클래스 컴포넌트에서는 bind 필수
        this.handleClick = this.handleClick.bind(this);
    }
    
    handleClick() {
    	this.setState({ count: this.state.count + 1 });
    }
    
    render(){
    	return(
            <button onClick={this.handleClick}>
            	Plus +1 ({this.state.count})
            </button>
        );
    }
}

 

클래스 컴포넌트에서 바인딩이 번거롭다면? 꼭 바인딩 하지 않아도 할 수 있는 방법이 생겼다.

 

 

바인딩 없이 클래스 컴포넌트를, 클래스 필드 문법

최신 클래스 필드 문법을 사용하면,

생성자 내부에 속성과 메서드를 정의하지 않고도 클래스의 속성을 직접 정의할 수 있게 해준다.

클래스 필드를 사용하면 함수 바인딩을 위한 생성자를 사용하지 않아도 된다.

화살표 함수를 클래스 필드에 항당해 간결하게 이벤트 핸들러를 작성할 수 있다.

 

import React from 'react';

export default class EventHandlingClassField extends React.Component{
    state = { count: 0 };
    
    handleClick= ()=> {
    	this.setState({ count: this.state.count + 1 });
    }
    
    render(){
    	return(
            <button onClick={this.handleClick}>
            	Plus +1 ({this.state.count})
            </button>
        );
    }
}

 

그렇지만 클래스 필드 문법이 있어도 현재는 클래스 컴포넌트는 거의 사용하지 않는다.

함수형 컴포넌트가 더 간결하고 가독성도 좋으며 훅을 사용해 상태관리와 생명주기 처리도 간편하기 때문이다.

또한 함수형 컴포넌트는 더 작은 번들 크기를 가지고 렌더링 성능도 더 우수한 경우가 많아서 성능 최적화의 장점과

순수 함수로 작성되므로 재사용성이 좋고, 이는 유지보수를 더 쉽게 할 수 있다.

 

 

함수형 컴포넌트의 이벤트 핸들러

함수형 컴포넌트에서는 화살표 함수를 이용해 간단하게 이벤트 핸들러를 다룰 수 있다.

화살표 함수를 사용하면 별도의 bind()메서드를 통한 작업이 없어도

이벤트 핸들러 내부에서 자동으로 올바른 컴포넌트 인스턴스를 가리키게 된다.

 

import React, { useState } from 'react';

export default function FunctionalComponent(){
    const [count, setCount] = useState(0);
    
    const handleClick = () => {
    	setCount(count + 1);
    };
    
    return(
        <button onClick={handleClick}>
            Plus +1 ({count})
        </button>
    );
}

 

바인딩도 필요 없고 딱 한눈에 보기에도 너무 쉽게 읽히는, 함수형 컴포넌트 코드다.

아래와 같이 이벤트핸들러를 정의할 때 화살표 함수를 사용하지 않고 일반 함수로도 정의할 수 있다.

 

import React, { useState }  from 'react';

export default function FunctionalComponent(){
    const [count, setCount] = useState(0);
    
    const handleClick() {
    	setCount(count + 1);
    };
    
    return(
        <button onClick={handleClick}>
            Plus +1 ({count})
        </button>
    );
}

 

그래도 혹시 모를 바인딩과 스코프 관련된 문제가 발생할 수 있기에

이벤트 핸들러 정의 시에 화살표 함수를 사용하는 것이 보다 일반적이고 권장되며

일반 함수와 화살표 함수를 선택 시 아래와 같은 상황에서 고려할 수 있다.

 

일반 함수

- 이벤트핸들러를 여러 곳에서 재사용 해야 할 때

- 이벤트 핸들러의 동작이 조건에 따라 달라질 때, 함수로 조건문을 적용해서 다르게 정의

- 클래스 컴포넌트와 동일한 방식으로 함수를 작성하고자 할 때

 

화살표 함수

- 스코프와 this바인딩 문제를 피할 수 있다. 고려하지 않아도 됨.

- 짧은 이벤트 핸들러 정의 시 가독성을 높일 수 있다.

- 다른 함수의 인자로 콜백함수를 전달할 때

- 클로저를 활용해 이벤트 핸들러 내부에서 외부 변수를 사용해야 할 때

화살표 함수를 사용해 클로저를 간단하게 만들 수 있다.