Hook 이란..?

이후띵·2022년 4월 1일
0

프론트_지식백과

목록 보기
7/8

한 줄 답변

  • Hook은 함수 컴포넌트에서 React state과 생명주기 기능을 “연동(hook into)”할 수 있게 해주는 함수입니다.
  • Hook은 React 16.8에 새로 추가된 기능입니다. Hook은 class를 작성하지 않고도 state와 다른 React의 기능들을 사용할 수 있게 해줍니다.

Hook 규칙

  1. 최상위에서만 Hook을 호출해야한다.

    💡 반복문, 조건문 혹은 중첩된 합수 내에서 Hook 호출 금지!
    • 잘못된 예
      if (name !== '') {
      	useEffect(function persistForm() {
            localStorage.setItem('formData', name);
        });
      };
    • 편안한 예
      useEffect(function persistForm() {
          // 👍 더 이상 첫 번째 규칙을 어기지 않습니다
          if (name !== '') {
            localStorage.setItem('formData', name);
          }
        });
    • Then Why? https://yeoulcoding.tistory.com/149?category=806488

      Hooks는 마법이 아니라 그저 배열일 뿐.

      리액트는 useState를 통해 생성한 상태를 접근하고 유지하기 위해서 useState메소드 바깥쪽에 state를 저장합니다. 이 state들은 선언된 컴포넌트를 유일하게 구분할 수 있는 키로 접근할 수 있으며 "배열" 형식으로 저장됩니다. 따라서 useState함수 안에서 선언되는 상태들은 이 배열에 "순서대로" 저장되며, 상태가 업데이트 되었을 때, 이 상태들은 리액트 컴포넌트 바깥에 선언되어 있는 변수들이기 때문에 업데이트 한 후에도 이 변수들에 접근할 수 있게 됩니다. 선언한 상태들이 컴포넌트를 키로 하는 배열에 '순서대로'저장되기 때문에 hooks 를 조건문이나, 일반 javascript함수 안에서 사용하게 된다면, 맨 처음 함수가 실행될때 저장되었던 순서와 맞지 않게 되어 엉뚱한 상태를 참조하게 될 수 있습니다. 이는 useState를 이용한 상태의 저장이 useState내부에 있는 것이 아니라 해당 컴포넌트 밖에 있기 때문입니다. 어떤 경우에는 2개의 useState hook이 실행되고 어떤 경우에는 3개가 실행된다면, 혹은 어떤 조건들로 인해서 hook이 실행되는 순서가 바뀌어 버리게 된다면, 함수가 렌더링될 때 참조하는 배열의 순서와 맞지 않기 때문에 엉뚱한 상태를 참조할 수도 있게 됩니다.
  2. 오직 React 함수 내에서 Hook을 호출해야 합니다

    💡 일반적인 JS 함수에서 호출 금지!
    • React 함수 컴포넌트에서 Hook을 호출!
    • Custom Hook에서 Hook을 호출!

Hook 의 종류 및 사용법

  • State Hook
    • useState
      1. useState 호출은 무엇을 하는 걸까요?
        • state 변수를 선언합니다!
        • 클래스 컴포넌트의 this.state이 제공하는 기능과 같습니다.
        • 일반적으로 일반 변수는 함수가 끝날 때 사라지지만, state 변수는 리액트에 의해 사라지지 않습니다.
      2. useState 인자로 무엇을 넘겨주나요?
        • state의 초기 값입니다.
      3. useState의 반환 값은 무엇인가요?
        • [state 변수, 해당 변수를 갱신할 수 있는 함수] 이 두 가지 쌍을 반환합니다.
    • 예시
      1:  import React, { useState } from 'react';
      2:
      3:  function Example() {
      4:    const [count, setCount] = useState(0);
      5:
      6:    return (
      7:      <div>
      8:        <p>You clicked {count} times</p>
      9:        <button onClick={() => setCount(count + 1)}>
      10:         Click me
      11:        </button>
      12:      </div>
      13:    );
      14:  }
      Line 1 - import useState Hook from react Line 4 - create state variable and the function which can renew the state. In this exercise, count 값 초기화 및 0으로 할당해주었습니다! Line 9: 사용자가 버튼을 누르면 setCount 함수를 호출하여 state 변수를 갱신합니다. 리액트는 새로운 count 변수를 Example 컴포넌트에 넘기며 해당 컴포넌트를 리렌더링 합니다.
  • Effect Hook
    • useEffect 💡 useEffect Hook은 componentDidMount, componentDidUpdate, componentWillUnmount가 합쳐진 것으로 생각해도 좋습니다.
  1. useEffect가 하는 일은 무엇일까요?
    - React에게 컴포넌트가 렌더링 이후에 어떤 일을 수행해야하는지 말합니다.
    - React는 우리가 넘긴 함수를 기억했다가(이 함수를 ‘effect’라고 부릅니다) DOM 업데이트를 수행한 이후에 불러낼 것입니다.
    - 이 외에도 데이터를 가져오거나 다른 명령형(imperative) API를 불러내는 일도 할 수 있습니다.

  2. useEffect를 컴포넌트 안에서 불러내는 이유는 무엇일까요?
    - useEffect 를 컴포넌트 내부에 둠으로써 effect를 통해 count
    state 변수(또는 그 어떤 prop에도)에 접근할 수 있게 됩니다.
    - 함수 범위 안에 존재하기 때문에 특별한 API 없이도 값을 얻을 수 있는 것입니다.
    - Hook은 자바스크립트의 클로저를 이용하여 React에 한정된 API를 고안하는 것보다 자바스크립트가 이미 가지고 있는 방법을 이용하여 문제를 해결합니다.
    3. useEffect는 렌더링 이후에 매번 수행되는 걸까요?
    - 네, 기본적으로 첫번째 렌더링과 이후의 모든 업데이트에서 수행됩니다. 마운팅과 업데이트라는 방식으로 생각하는 대신 effect를 렌더링 이후에 발생하는 것으로 생각하는 것이 더 쉬울 것입니다. React는 effect가 수행되는 시점에 이미 DOM이 업데이트되었음을 보장합니다.
    4. effect에서 함수를 반환하는 이유는 무엇일까요?
    - 이는 effect를 위한 추가적인 정리(clean-up) 메커니즘입니다. 모든 effect는 정리를 위한 함수를 반환할 수 있습니다. 이 점이 구독(subscription)의 추가와 제거를 위한 로직을 가까이 묶어둘 수 있게 합니다. 구독(subscription)의 추가와 제거가 모두 하나의 effect를 구성하는 것입니다.
    5. React가 effect를 정리(clean-up)하는 시점은 정확히 언제일까요?
    - React는 컴포넌트가 마운트 해제되는 때에 정리(clean-up)를 실행합니다. 하지만 위의 예시에서 보았듯이 effect는 한번이 아니라 렌더링이 실행되는 때마다 실행됩니다. React가 다음 차례의 effect를 실행하기 전에 이전의 렌더링에서 파생된 effect 또한 정리하는 이유가 바로 이 때문입니다.
    6. 보충자료
    https://ko.reactjs.org/docs/hooks-effect.html
    - 예시

    ```jsx
    useEffect(() => {
      function handleStatusChange(status) {
        setIsOnline(status.isOnline);
      }
    
      ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
      return () => {
        ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
      };
    });
    ```
    - 정리(clean-up)가 필요없는 경우에는 어떤 것도 반환하지 않습니다.
  • Custom Hook

    • 자신만의 Hook을 만들면 컴포넌트 로직을 함수로 뽑아내어 재사용 할 수 있습니다.

    • 예시로 확인하시죠!

      DayList.js 단독으로 사용!

            // DayList.js
            import { useEffect, useState } from 'react';
            import { Link } from 'react-router-dom';
      
            export default function DayList() {
              const [days, setDays] = useState([]);
      
              useEffect(() => {
                fetch('http://localhost:3001/days')
                  .then((res) => {
                  return res.json();
                })
                  .then((data) => {
                  setDays(data);
                });
              }, []);
      
              return (
                <ul className='list_day'>
                  {days.map((day) => {
                    <li key={day.id}>
                      <Link to={`/day/${day.day}`}>Day {day.day}</Link>
                    </li>;
                  })}
                </ul>
              );
            }

      DayList.js에서 useFetch.js(커스텀 훅) 사용!

    • useFetch.js

      import { useEffect, useState } from 'react';
      
      export default function useFetch(url) {
        const [data, setData] = useState([]);
      
        useEffect(() => {
          fetch(url)
            .then((res) => {
            return res.json();
          })
            .then((data) => {
            setData(data);
          });
        }, [url]);
        return data;
      }
    • DayList.js

      import { Link } from 'react-router-dom';
      import useFetch from '../hooks/useFetch';
      
      export default function DayList() {
          const days = useFetch('http://localhost:3001/days');
          return (
            <ul className='list_day'>
              {days.map((day) => {
                <li key={day.id}>
                  <Link to={`/day/${day.day}`}>Day {day.day}</Link>
                </li>;
              })}
            </ul>
          );
      }
  • 특정 api를 호출하여 데이터를 불러오는 요청을 할 경우, 커스텀 훅을 통해 코드를 재사용할 수 있다는 장점이 있네요!

  • 여러 컴포넌트에서 커스텀 훅을 통해 편리하게 사용할 수 있겠군요!

profile
이후띵's 개발일지

0개의 댓글