우리가 리액트에서 Hooks 를 사용하는 이유

제이밍·2021년 10월 6일
3

Hook이 뭔가요?

  1. Class 바탕의 코드를 작성할 필요 없이 상태 값과 여러 React의 기능을 사용할 수 있게합니다.

  2. Hook은 함수 컴포넌트에서 React state와 생명주기 기능(lifecycle features)을 연동할 수 있게 해주는 함수 등이 있습니다. Hook은 class 안에서는 동작하지 않습니다. 대신 class 없이 React를 사용할 수 있게 해주는 것입니다.

Hook가 나오게된 배경

1. 컴포넌트 사이에서 상태로직을 재사용하기 어렵습니다.

  • Hook을 사용하면 컴포넌트로부터 상태 관련 로직을 추상화할 수 있습니다.
  • 독립적인 테스트와 재사용이 가능합니다.
  • Hook은 계층의 변화 없이 상태 관련 로직을 재사용할 수 있도록 도와줍니다.

2. 복잡한 코드를 간단하게 나타낼 수 있습니다.

  • Hook을 통해 서로 비슷한 것을 하는 작은 함수의 묶음으로 컴포넌트를 나누는 방법을 사용할 수 있습니다.

3. Class는 혼란을 줄 수 있습니다.

  • class 사용을 위해 필수적인 this 키워드가 어떻게 작동하는지 알아야 하기 때문에 이는 사용자들에게 큰 혼란을 주었으며, 코드의 재사용성과 구성을 어렵게 만들었습니다.
  • Hook은 Class없이 React 기능들을 사용하는 방법을 제시합니다.

Hooks 의 종류

1. 📌 State Hook

import React, { useState } from 'react';

function Example() {
  // "count"라는 새 상태 변수를 선언합니다
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
  • 위 코드에서 보이는 useState가 바로 Hook 입니다.
  • useState는 현재의 state 값과 이 값을 업데이트하는 함수를 쌍으로 제공합니다.
  • useState() 안에 들어가는 초기값은 첫 번째 렌더링에만 딱 한번 사용됩니다.

2. ⚡️ Effect Hook

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
  • useEffect는 함수 컴포넌트 내에서 이런 side effects를 수행할 수 있게 해줍니다.
  • useEffect를 사용하면, React는 DOM을 바꾼 뒤에 “effect” 함수를 실행할 것입니다
  • Effect를 “해제”할 필요가 있다면, 해제하는 함수를 반환해주면 됩니다.
  • class 컴포넌트에서는 생명주기 메서드를 사용해 각각 쪼개서 넣어야만 했다면 Hook를 사용하면 코드를 한군데에 모아서 작성 할 수 있게 됩니다.

3. 🔌 다른 내장 Hook인 useContext, useReducer

useContext는 컴포넌트를 중첩하지 않고도 React context를 구독할 수 있게 해줍니다.

4. 이외 기타 hooks

1. useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
  1. 메모이제이션된 콜백을 반환합니다.
  2. 불필요한 렌더링을 방지하기 위해 참조의 동일성에 의존적인 최적화된 자식 컴포넌트에 콜백을 전달할 때 유용합니다.

2. useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  1. 메모이제이션된 값을 반환합니다.
  2. useMemo는 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산하여 모든 렌더링 시 고비용 계산을 방지해 최적화 해줍니다.
  3. useMemo로 전달된 함수는 렌더링 중에 실행된다는 것을 기억하세요. 통상적으로 렌더링 중에는 하지 않는 것을 이 함수 내에서 적용하면 안됩니다.

3. useRef

일반적인 유스케이스는 자식에게 명령적으로 접근하는 경우입니다.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}
  1. DOM에 접근하는 방법으로 사용됩니다.
  2. useRef()는 순수 자바스크립트 객체를 생성하기 때문하기 때문에 ref 속성보다 유용합니다.
  3. 본질적으로 useRef는 .current 프로퍼티에 변경 가능한 값을 담고 있는 "상자"라고 표현합니다.

4. useImperativeHandle

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
  1. useImperativeHandle은 ref를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다
  2. 예시에서 <FancyInput ref={inputRef} />를 렌더링한 부모 컴포넌트는 inputRef.current.focus()를 호출할 수 있습니다.

5. useLayoutEffect

  1. 이 함수는 useEffect와 동일하긴 한데, 모든 DOM 변경 후에 동기적으로 발생합니다.
  2. DOM에서 레이아웃을 읽고 동기적으로 리렌더링하는 경우에 사용하세요.
  3. 먼저 useEffect를 사용해 보고 문제가 있다면 그다음으로 useLayoutEffect를 사용해 보기를 권합니다.

6. useDebugValue

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // ...

  // Show a label in DevTools next to this Hook
  // e.g. "FriendStatus: Online"
  useDebugValue(isOnline ? 'Online' : 'Offline');

  return isOnline;
}

1.useDebugValue는 React 개발자도구에서 사용자 Hook 레이블을 표시하는 데에 사용할 수 있습니다.

✌️ Hook 사용 규칙

  • 최상위(at the top level)에서만 Hook을 호출해야 합니다. 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하지 마세요.
  • React 함수 컴포넌트 내에서만 Hook을 호출해야 합니다. 일반 JavaScript 함수에서는 Hook을 호출해서는 안 됩니다.

Reference

https://ko.reactjs.org/docs/hooks-intro.html

profile
모르는것은 그때그때 기록하기

0개의 댓글