React - Hooks정복하기

강종연·2021년 6월 14일
0

React

목록 보기
1/1


리액트에서는 이전까지 클래스형 컴포넌트 위주의 개발을 했었다. 하지만 Hooks가 나온 이후 상황이 완전히 바뀌었다. 함수형 컴포넌트위주의 웹 개발 상황이 펼쳐진 것이다.
이것이 왜 가능하게됐으며 Hook이 무엇인지, 종류가 어떤 것이 있는지 등등을 적어보고자 한다.

Hook의 등장

React 버전 16.8부터 새로 추가된 Hook은 더이상 상태값을 포함한 여러 React의 기능을 함수에서 사용하게 만들었다. 기존에 클래스형 컴포넌트에서 상태관리나 성능최적화를 할려면 복잡했으나 Hook이 등장하면서 쉽고 간편하게 이용할 수 있다.

Hook이란?

React 공식문서에 나온 내용

Hook은 함수 컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 “연동(hook into)“할 수 있게 해주는 함수입니다.

Hook의 종류

상황에 따라 사용하는 Hook의 종류는 다르다. 상황별로 Hook을 분류하고자 한다.

상태관리

가변적인 상태를 관리한다.

useState

import { useState } from "react";

const [value, setValue] = useState(0);

react모듈에서 useState Hook을 불러온다. 그 후 위의 코드와 같이 선언해주자. 배열의 첫번째(value)는 상태관리를 할 값이고 두번째(setValue)는 바뀐 값을 적용할 때 사용한다.

useState안의 파라미터는 value값의 초기값을 설정해주자. 지금은 0을 넣었고 null값이나 다른 값들도 넣을 수 있다.

const onClick = () => setValue(value + 1);

onClick 함수안에는 setValue에 대해서 적혀져 있다. onClick함수를 실행하면 value값은 현재의 값에서 +1로 상태가 업데이트된다.

useState는 한번만 쓸 수 있는 것이 아닌 여러번 사용이 가능하다.

useReducer

import { useReducer } from "react";

const [state, dispatch] = useReducer(reducer, initialState);

useState의 대체함수이다. 하나의 상태를 관리하는 useState에 반해 useReducer은 여러 상태를 관리한다.

첫번째로 받는 인자인 함수 reducer는 값이 어떠한 타입을 갖느냐에 따라 케이스 분류를 하는 함수이다.

//counter의 함수 reducer 예시
function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

위 처럼 reducer함수는 switch문을 사용하여 케이스를 분류하고 알맞는 행위들을 연결한다.

두번째로 받는 initialState는 상태관리를 할 것의 초깃값을 나타낸다. 이후 변경되는 값들은 업데이트된다.

useReducer는 배열을 반환하는데 그 안에는 현재상태를 나타내는 state와 타입에 따라 행위를 실행할 함수인 dispatch를 반환한다.

//상태값 설정
Count: {
  state.count;
}

//dispatch예시
<button onClick={() => dispatch({ type: "increment" })}>+</button>;

useState와 비교해서 더 자세하기에 useReducer이 더 좋다고 생각할 수 있다. 하지만 비교적 경우의 수가 적은 상황에서 useReducer을 사용하기엔 불필요하게 코드길이가 길어질 수 있다. 그렇기에 상황에 맞게 적절하게 사용하도록 하자.


동작 관리

useEffect
React 컴포넌트 안에서 데이터를 가져오거나 만들고, DOM을 조작하는 등 이러한 모든 동작을 side effects라고 한다. 이 작업을 함수 컴포넌트 내에서 수행할 수 있도록 해주는 것이 useEffect(Effect Hook)이다.

클래스형 컴포넌트를 사용하는 리액트 프로젝트에서는 componentDidMount, componentDidUpdate, componentWillUnmount로 side effects를 수행하지만 함수 컴포넌트에서는 Hook을 이용해 하나로 통합한 useEffect를 사용하여 수행한다.

import React, {useEffect} from 'react';

function ExampleEffect() {

  const turnOn = () => {
    ...
  }

  useEffect(() => {
    turnOn();
  })

  return <div>this is ExampleEffect</div>
}

첫번째 인자에는 side effects를 할 함수를 넣어서 수행합니다. 두번째 인자에는 특정한 배열을 넣어 배열안의 값이 변경될 때만 useEffect가 실행할 수 있게 만든다.


재사용하기

컴포넌트가 렌더링 될 때 마다 상태나 함수 등은 리액트의 특성에 의해 새로 생성된다는 단점이 있다. 이럴 때 쓰이는 것이 재사용관련 HOOK이다.

useCallback

import { useCallback } from "react";

const onCreateUseCallback = useCallback(() => {
  createHappyBox(a);
}, [a]);

useCallback은 react모듈에서 받아와 쓰이는데 함수와 배열을 인자로 갖는데 배열안의 값이 변경되었을 때만 함수의 버전이 변경된다. 함수의 현재 값을 저장해놓는 것을 메모이제이션 이라고 하는데 인자로 갖는 배열(의존성 값의 배열)이 변경될 때만 메모이제이션 버전이 업데이트되고 그렇지 않으면 변경이 되지 않는다. 그 후 메모이제이션 된 함수를 반환하는 것이 useCallback이다.

useMemo

import { useMemo } from "react";

const onCreateUseMemo = useMemo(() => {
  createHappyBox(a);
}, [a]);

위에서 useCallback에 대한 설명을 봤으면 의문이 가질 것이다.

왜 형태가 똑같지?

useMemo와 useCallback은 매우 유사하게 작동이 이루어진다. 하지만 useCallback은 함수를 반환하는 것에 비해, useMemo는 값을 반환한다는 차이점이 존재한다.

그래서 onCreateUseCallback에는 메모이제이션된 함수(createHappyBox(a))가 담겨져 있고 onCreateUseMemo에는 메모이제이션된 값(createHappyBox(a) 이 반환한 값)이 담겨져 있다.

이런 재사용관련 Hook을 씀으로 인해 메모리와 시간을 아낄 수 있다.

기타 Hooks

Hook API의 종류는 위에서 정리한 것보다 훨씬 많다. useContext, useRef, useDebugValue 등등.. 직접 만드는 커스텀 Hook도 있으나 나머지는 공식문서를 참고하길 바란다.

글을 마무리하며

오늘은 최근 리액트의 가장 중요한 요소인 Hook을 알아보았다. React는 Hook이 나온 뒤 함수형 컴포넌트의 개발형태로 바뀌면서 굉장히 많은 변화가 일어났다.

Hook이 탄생하기 이전에는 class로 짜여진 것이 대부분일텐데 이것들을 완전히 버리고 전면 바꾸라는 소리는 아니다. (React 공식 발표상에서도 아니라 함.)

단지 이제 개발되는 프로젝트들은 Hook을 쓰는 것이 더 유리할 것이기에 Hook API가 중요하다고 하는 것이다. 우선적으로 Hook에 대해 공부하고 과거의 코드를 관리할 일이 생긴다면 그 때 class에 관련된 것들을 알아보도록 하자.

profile
TypeScript, Next.js를 좋아하는 프론트엔드 개발자입니다:)

0개의 댓글