늘 겸손하게

React 함수형 컴포넌트, 클래스형 컴포넌트 본문

Programming/React

React 함수형 컴포넌트, 클래스형 컴포넌트

besforyou999 2022. 7. 9. 15:29

React에서는 컴포넌트를 만들기 위해 함수형 문법 혹은 클래스형 문법을 사용할 수 있습니다. 컴포넌트를 만드는 두 가지 방법들의 특징을 알아보겠습니다.

 

클래스형 컴포넌트는 React의 기능을 100% 활용할 수 있습니다. 하지만 함수형 컴포넌트는 컴포넌트 내부의 state를 만들어 사용할 수 없고 컴포넌트 라이프사이클 API를 사용할 수도 없었습니다. 그래서 상위 컴포넌트가 시키는 단순한 일만 처리하는 컴포넌트였습니다. 하지만 리액트 hook이 도입되면서 함수 스타일에서도 state와 라이프사이클 API를 사용 가능하게 되었습니다. 

 

React 16.8부터 React hook이 도입되고 공식문서에서도 함수형 컴포넌트와 hook 사용을 권장하고 있습니다.

그렇지만 클래스형 컴포넌트도 계속 지원한다고 하니 둘 다 알아두면 상황에 알맞은 방식으로 컴포넌트를 사용할 수 있을 것입니다.

 

두 가지 방식의 차이점을 알아보자.

 

< 예시 코드 >

 

쉬운 설명을 위한 App 컴포넌트, FuncComp 컴포넌트, ClassComp 컴포넌트

 

FuncComp, ClassComp는 App 컴포넌트의 자식 컴포넌트입니다.

 

function App() {
    return (
      <div className='container'>
        <h1>Hello world</h1>
        <FuncComp></FuncComp>
        <ClassComp></ClassComp>
      </div>
    );
}

function FuncComp() {
  return (
    <div className='container'>
      <h2>function style component</h2>
    </div>
  );
}

class ClassComp extends React.Component {
  render() {
    return (
      <div className='container'>
        <h2>class style component</h2>
      </div>
    )
  }
}

 

1. props 받는 방식

 

클래스형 컴포넌트 -> this.props 통해 받아야 함

 

함수형 컴포넌트 -> 매개변수로 받는 것이 가능

 

 

< 예시 >

 

initNumber={2}를 주어 숫자 2를 전달

 

function App() {
    return (
      <div className='container'>
        <h1>Hello world</h1>
        <FuncComp initNumber={2}></FuncComp>
        <ClassComp initNumber={2}></ClassComp>
      </div>
    );
}

 

클래스형 컴포넌트 : this.props를 통해 받음

 

class ClassComp extends React.Component {
  render() {
    return (
      <div className='container'>
        <h2>class style component</h2>
        <p>Number : {this.props.initNumber}</p>
      </div>
    )
  }
}

 

 

함수형 컴포넌트 : 매개변수로 받음

 

function FuncComp({number}) {
  return (
    <div className='container'>
      <h2>function style component</h2>
      <p>Number : {number}</p>
    </div>
  );
}

 

 

함수형 컴포넌트로 조금 더 간단하게 받을 수 있다.

 

 

 

2. state 사용방식

 

클래스형 컴포넌트

  • state 변경 위해 this.setState 사용
class ClassComp extends React.Component {
  state = {
    number: this.props.initNumber
  }
  render() {
    return (
      <div className='container'>
        <h2>class style component</h2>
        <input type="button" value="random" onClick= {
          function() {
            this.setState({number: Math.random()})
          }.bind(this)
        }></input>
      </div>
    )
  }
}

 

함수형 컴포넌트 -> useState hook 사용

 

function FuncComp({number}) {
  let [number, setNumber] = useState(props.initNumber);
  
  console.log('numberState', numberState);
  return (
    <div className='container'>
      <h2>function style component</h2>
      <p>Number : {number}</p>
      <input type="button" value="random" onClick={
        function() {
          setNumber(Math.random());
        }
      }</input>
    </div>
  );
}

 

 

함수형 컴포넌트는 useState hook으로 클래스 컴포넌트는 객체 안에 state를 선언해서 사용한다.

 

 

 

3. 라이프사이클 함수 ( 생명주기 함수 )

 

클래스 컴포넌트에서는 컴포넌트 생명주기 함수로 원하는 시점에 원하는 코드를 실행할 수 있습니다.

최근에 hook이 추가된 이후 함수형 컴포넌트에서도 생명주기 함수 실행이 가능해졌습니다.

 

 

클래스 컴포넌트 

 

class ClassComp extends React.Component {
    state = {
        number : this.props.initNumber,
        date: (new Date()).toString()
    }

    componentWillMount() {
        console.log("class => componentWillMount");
    }

    componentDidMount() {
        console.log("class => componentDidMount");
    }

    shouldComponentUpdate(nextProps, nextState) {
        console.log("class => shouldComponentUpdate");
    }

    componentWillUpdate(nextProps, nextState) {
        console.log("class => componentWillUpdate");
    }

    componentDidUpdate(nextProps, nextState) {
        console.log("class => componentDidUpdate");
    }
    
    render() {
        return (
        <div className='container'>
            <h2>class style component</h2>
            <p>Number : {this.props.initNumber}</p>
        </div>
        )
    }
}

 

 

함수형 컴포넌트 - useEffect ( componentDidMount & componentDidUpdate & componentWillUnmount )

 

function FuncComp({number}) {

    useEffect(function(){
        console.log("FuncComp => useEffect");
    })
    
    return (
        <div className='container'>
        <h2>function style component</h2>
        <p>Number : {number}</p>
        </div>
    );
}

 

4. clean up

 

컴포넌트가 제거되기 전에 할 작업 처리

 

함수형 -> useEffect의 return 값에 구현

클래스형 -> componentWillUnmount에 구현

 

함수형

 

useEffect(function(){
    console.log("FuncComp => useEffect");
    return function() {
        // clean up
    }
})

 

클래스형

 

componentWillUnmount() {
    // clean up
}

 

 

5. skipping effect

 

클래스형 컴포넌트에서 불필요한 이펙트를 넘어가기 위해 componentDidUpdate에서 이전 state와 현재 state값을 비교하여 변경된 점이 있을 때만 이펙트가 발생하도록 구현했습니다.

 

< 예 >

 

componentDidUpdate(prevProps, prevState) {
    if (prevState.count !== this.state.count) {
        document.title = 'You clicked ${this.state.count} times';
    }
}

 

 

함수형 컴포넌트에서 이펙트 넘어가기는 어떻게 구현할까?

-> useEffect의 두 번째 인자

 

< 예시 >

 

useEffect(function() {
	document.title = number
})

 

위 코드는 document.title를 바꾸는 side effect가 실행된다. number값이 바뀐 경우에만 side effect가 실행되도록 하고 싶다면

 

두 번째 인자로 [number]를 전달한다.

 

useEffect(function() {
    document.title = number
}, [number])