React - class컴포넌트와 function 컴포넌트의 차이점에 대해 알아보자.
개요
훅이 도입되며 function component
의 사용은 상태가 없는 컴포넌트에 주로 사용되었으나 훅이 나오며 function component
에도 상태가 추가되고 이제 새로 작성되는 컴포넌트의 작성을 대부분 class component
에서 function component
를 사용하게 되고 있습니다. 근데 과연 class 와 function 의 차이는 작성법 말고 무엇이 있을까요?
function component는 랜더되는 당시의 값으로 기억하고 사용한다.
차이점을 위한 컴포넌트 예시
우선 버튼을 클릭하면 2초 뒤에 부모로부터 받은 결제금액을 alert 으로 보여주는 컴포넌트를 class
, function
컴포넌트로 각각 작성해 보도록 하겠습니다.
function component
function PaymentButtonF({pay}) { const payment = () => alert(`결제금액 : ${pay}`); const onPayClick = () => setTimeout(payment, 2000); return ( <button onClick={onPayClick}>결제 (함수형 컴포넌트)</button> ); } export default PaymentButtonF;
class component
class PaymentButtonC extends React.Component { payment = () => alert(`결제금액 : ${this.props.pay}`); onPayClick = () => setTimeout(payment, 2000); render() { return <button onClick={onPayClick}>결제 (클래스 컴포넌트)</button>; } } export default PaymentButtonC;
이제 각 payment
컴포넌트들을 자식으로 사용하고 pay를 전달하는 부모 컴포넌트를 작성해보도록 하겠습니다.
두가지를 선언하는 부모 컴포넌트
import React, {useState} from "react"; import PaymentButtonC from "./PaymentButtoonC"; import PaymentButtonF from "./PaymentButtonF"; function Payment() { const [pay, setPay] = useState(0); console.log(pay); return ( <> <input value={pay} onChange={e => setPay(e.target.value)}/> <PaymentButtonC pay={pay}/> <PaymentButtonF pay={pay}/> </> ); } export default Payment;
구동하는 방식은 동일한 것처럼 보이지만 위에서 말한 차이점을 생각해서 보시면 분명한 차이점이 존재합니다. 자 이제 두 코드의 실행결과를 확인해 보도록 하겠습니다.
function component 실행결과
class component 실행결과
둘의 실행결과는 다음과 같습니다.
- function component : 클릭시점의 pay 값을 2초 뒤에 노출
- class component : 클릭시점이 아닌 2초뒤에 이벤트 발생시점의 pay를 노출
이와 같이 class component 로 작성 할 경우 내가 이벤트를 발생시켜도 딜레이가 발생하고 그사이에 이벤트의 필요한 값이 변경된다면 내가 의도하지 않은 결과가 나올 수 있습니다.
class component에서의 동작 방식
위의 두개의 예시를 다시 자세히 보면 클래스 컴포넌트는 this를 통해 값을 조회하는 것을 볼 수 있습니다.
payment = () => alert(`결제금액 : ${this.props.pay}`); onPayClick = () => setTimeout(payment, 2000);
this 의 경우는 값이 변동되면 이에 따라 게속 변경됩니다. 때문에 이를 참조할때 이벤트가 최초 시작되는 것이 아닌 발생하는 시점에 this 에 있는 최신값을 가져오기때문에 의도하지 않은 결과가 나올 수 있게 됩니다.
해결방법
class component 에서 위와 같은 방법을 해결하기 위해선 다음과 같은 방식들로 해결 할 수 있습니다.
구조 분해 할당
payment = (pay) => alert(`결제금액 : ${pay}`); onPayClick = () => { const {pay} = this.props; setTimeout(()=> this.payment(pay), 2000) };
위와 같이 이벤트 선언전 this 에 대해 독립시켜 고정시키는 방식으로 선언한다면 이벤트를 클릭한 시점의 값으로 정보를 처리할 수 있습니다.
클로저 방식
class PaymentButtonC extends React.Component { render() { const props = this.props; const payment = () => alert(`결제금액 : ${props.pay}`); const onPayClick = () => setTimeout(payment , 2000); return <button onClick={onPayClick}>결제 (클래스 컴포넌트)</button>; } } export default PaymentButtonC;
클로저의 방식으로 아에 render 시점에 전부 props 를 가둬두었기 때문에 동일하게 동작하게 됩니다. 결국 이런 render 내부에서 함수를 정의하는 방식이 간결하게 표현하기 위해 결국 function 컴포넌트를 사용하게 됩니다.
참조
- https://www.hamadevelop.me/reactfunctionclassdiff/?fbclid=IwAR1XfCStwBaDiw-rWzQ1ftFrcZx62_cWQ48uwI_UzHblA93DS8P7msgAhAA