React 함수형 컴포넌트와 필수 Hook

에듀캐스트 장고&리액트 강의를 듣고 정리하는 글이다.

클래스형 컴포넌트의 한계

  • 클래스가 코드 재사용성과 코드 구성을 더 어렵게 만든다.
  • 자바스크립트의 this는 다른 언어와 다르게 작동하며, 개발자는 이벤트 핸들러가 등록되는 방법을 기억해야만 한다.
  • 부수적으로 작성해야하는 코드가 많다.
  • 서로 연관성이 없는 다수 로직을 하나의 생명주기 메서드에서 구현하는 경우가 많다.
  • 코드 압축이 잘 안되는 경우가 있고, 컴파일 단계에서 코드 최적화를 어렵게 만든다.
  • componentDidMount에서 등록하고 ComponentWillUnmount에서 해제를 깜발할 수 있다. (setInterval같은 함수 해제 깜박하는 등)

함수형 컴포넌트를 사용하자.

함수형 컴포넌트

  • 클래스형 컴포넌트에 적용했던 것들을 대부분 적용 가능 (Hook을 활용)
  • 현재 리액트 팀에서도 함수형 컴포넌트와 Hook 개발에 집중하고 있다.
    • 그래서 리액트를 시작할 때 함수형 컴포넌트를 쓰기를 권장한다.
    • 클래스 컴포넌트에 대한 호환성을 보장한다.

다음은 클래스형 컴포넌트 예시인데, 아래처럼 바꿀 수 있다.

클래스형 컴포넌트

class Message1 extends React.Component{
  render(){
    return (
      <div>{this.props.message}</div>
    )
  }
}

####함수형 컴포넌트

const Message2 = (props) => (
  <div>{props.message}</div>
);

const Message3 = ({message}) => (
  <div>{message}</div>
);

필수 Hooks (useState, useEffect, userCallback)

  • 리액트 버전 16.8에 새로이 추가되었다.
  • Hook을 통해 함수형 컴포넌트에서도 상태값과 여러 React의 기능을 활용할 수 있다.
    • props, state, context, refs, life-cycle에 대해 보다 직관적인 API를 제공한다.
    • 같은 로직을 한 곳으로 모을 수 있어서 가독성에 좋다.
    • 클래스형 컴포넌트에서 사용하려면, 커스텀 Wrapper 컴포넌트가 필요하다.

userState 훅

컴포넌트 내에서 상태값을 유지/변경하고 싶을 때 사용한다. 단, 주의해야할 점으로 useState 훅은 이전 상태값을 모두 지우기 때문에, 통으로 변경해주어야 한다.

// 아래처럼 useState 함수를 import 해준다.
import {useState} from "react";

function App2() {
  const [value1, setValue1] = useState(0);
  const [value2, setValue2] = useState(0);
  const [value, setValue] = useState({ value1: 0, value2: 0 }); // 상태값을 바꿀때 다 바꿔줘야한다.
  const onClick = () => {
    setValue((prevState) => ({ ...prevState, value1: 10 }));
  };
  return (
    <div>
      Hello App2
      <hr />
      {JSON.stringify(value)}
      <button onClick={onClick}>Button</button>
    </div>
  );
}

useEffect 훅

생명주기의 componentDidMount와 componentDidUpdate에 대응한다.

  useEffect(() => {});  // render 시에 호출
  useEffect(() => {}, []); // mount 시에만 호출
  useEffect(() => {}, [value]); // value가 변경될 시에 호출
  useEffect(() => {
    return () => {};
  }, [value]); // unmount 시에 호출된다. clearInterval 같은 곳에 사용