티스토리 뷰

React

[생활코딩] React class vs function

Sunny K 2020. 11. 15. 20:03
이 글은 생활코딩의 React class & function style coding 수업을 듣고 정리한 내용입니다.

 

수업내용

React는 classfunction 두 가지 방법으로 작성할 수 있다.

class 방식은 React의 모든 기능을 사용할 수 있지만 해당 문법을 모두 알아야 하고, function 방식은 간편하지만 state를 만들거나 life cycle API를 사용할 수 없이 상위 컴포넌트가 시키는 일만 해야 했다. 하지만, hook이 도입되면서 function 방식도 내부적으로 상태(state)를 다루고, 라이프 사이클에 따른 작업을 정의할 수 있게 되었다. 그러면서 함수형의 간편함은 그대로 가진다.

생활코딩의 React class & function style coding 수업은 같은 일을 하는 컴포넌트를 class와 function 두 가지 방식으로 각각 작성해보며 서로의 차이를 알고 이해하기 위한 수업이다.

 

React class vs function

기본 형태

class

import React from 'react'

export default class ClassComp extends React.Component {
  render() {
    return (
      <div className="container">
        <h2>Class Style Component</h2>
      </div>
    )
  }
}
  • render() 함수에서 return

function

import React from 'react'

export default function FuncComp() {
  return (
    <div className="container">
      <h2>Function Style Component</h2>
    </div>
  )
}
  • 그 자체에서 return

 

state

컴포넌트의 상태 정보를 가지는 state에 대해 실습하기 위해 App컴포넌트에서 initNumber를 전해준다. 하위 컴포넌트에서는 전달받은 initNumberstate에 저장후 화면에 출력한다. 이후, 랜덤한 숫자로 상태를 업데이트해주는 버튼을 추가한다.

App.js

export default class App extends React.Component {
  render() {
    return (
     <div className="container">
      <FuncComp initNumber={2}></FuncComp>
      <ClassComp initNumber={2}></ClassComp>
    </div>
    )
  }
}

class

export default class ClassComp extends React.Component {
  state = {
    number: this.props.initNumber
  }

  render() {
    return (
      <div className="container">
        <h2>Class Style Component</h2>
        <p>Number : {this.state.number}</p>
        <input type="button" value="random" onClick={
          function () {
            this.setState({ number: Math.random() })
          }.bind(this)
        } />
      </div>
    )
  }
}
  • state에 상태관리
  • this.props 사용
  • this.state에서 상태 정보 가져옴
  • setState()로 상태 업데이트

function

import React, { useState } from 'react'

export default function FuncComp(props) {
  const [number, setRandomNumber] = useState(props.initNumber)

  return (
    <div className="container">
      <h2>Function Style Component</h2>
      <p>Number : {number}</p>
      <input type="button" value="random" onClick={
        function () {
          setRandomNumber(Math.random())
        }
      } />
    </div>
  )
}
  • 첫 번째 파라미터로 props를 받아옴
  • import {useState} from 'react'
  • React hook의 useState()를 이용하여 상태 관리
  • useState()의 인자는 state의 초기 값
  • [state 변수 이름, state를 업데이트하는 함수] <- 배열 구조 분해 문법으로 아래와 같은 일을 한다
    const numberState = useState(props.initNumber)
    const number = numberState[0]
    const setRandomNumber = numberState[1]

 

React Lifecycle

React Lifecycle

class

export default class ClassComp extends React.Component {
  state = {...}

  // 처음 컴포넌트를 그리기 전 사전작업
  // 이후 render() 호출
  componentWillMount() {
    console.log('class => componentWillMount')
  }

  // 처음 컴포넌트를 render한 이후 호출
  componentDidMount() {
    console.log('class => componentDidMount')
  }

  // 기존 props, state와 새로운 값을 비교하여 render를 호출해야 하는지 검사
  // return값이 true이면 componentWillUpdate 호출
  shouldComponentUpdate(nextProps, nextState) {
    console.log('class => shouldComponentUpdate')
    return true
  }

  // 컴포넌트를 다시 그리기 전 호출
  componentWillUpdate(nextProps, nextState) {
    console.log('class => componentWillUpdate')
  }

  // 컴포넌트를 다시 그리고 호출
  componentDidUpdate(nextProps, nextState) {
    console.log('class => componentDidUpdate')
  }

  // 컴포넌트를 화면에 그림
  render() {
    console.log('class => render')
    return (...)
  }
}

function

export default function FuncComp(props) {

  const [number, setRandomNumber] = useState(props.initNumber)

  // 두 번째 인자인 배열내의 것의 상태가 바뀌면 첫 번째 인자인 콜백함수 호출
  // 빈 배열 전달 시 최초 1회만 실행되고 그 이후에는 실행되지 않음
  useEffect(function () {
    console.log("function => useEffect (componentDidMount)")

    // effect이후 clean up 작업
    return function () {
      // 컴포넌트가 삭제될 때 실행
      console.log("function => useEffect return (componentWillUnMount)")
    }
  }, [])

  // 두번째 인자로 전달된 배열에 number가 있음
  // number의 상태가 바뀌면 첫 번째 인자인 함수가 호출됨
  // side effect(부가적인 작용)
  useEffect(
    function () {
      console.log("function => useEffect number(componentDidMount & componentDidUpdate)")

      return function () {
        console.log("function => useEffect number return (componentDidMount, componentDidUpdate & componentWillUnmount)")
      }
    },
    [number]
  )

  console.log("function => render")
  return (...)
}
  • hook의 useEffect 사용
  • useEffectcomponentDidMount, componentDidUpdate, componentWillUnmount가 합쳐진 것으로 생각할 수 있음
  • useEffectreturn 하는 함수는 clean up(정리)의 역할을 가짐. 어떤 작업을 한 이후 뒤처리 작업이라고 생각할 수 있음.

실행 예시

  • 컴포넌트 생성

     

    Mount component
  • state 변경
    ClassComp의 상태 업데이트
    FuncComp의 number 상태 업데이트
  • 컴포넌트 삭제
    ClassComp 삭제
    FuncComp 삭제

 

 

 


 

참고 사이트

댓글