フックマスターになりたい (1): 커스텀 훅!

9rganizedChaos·2021년 9월 24일
0
post-thumbnail

리액트 컴포넌트를 처음 학습할 때, 컴포넌트란 "나만의 태그"라고 정의했던 기억이 난다. 좀 더 명확하게 컴포넌트란 props를 인풋으로 받아 DOM을 렌더하는, JSX를 리턴하는 단위(함수, 혹은 클래스)이다. 조금 오해의 소지는 있지만 단순하게는 (자바스크립트가 가미된) 재사용이 가능한 html 태그 더미라고 할 수도 있지 않을까? 컴포넌트의 제1 장점으로는 언제나 "재사용성"이 꼽히니까.

그런데 우리가 html 태그 더미를 재사용할 수 있다면, 컴포넌트 내에서 반복되는 함수 로직도 분리해서 여러 차례 재사용할 수도 있지 않을까? 이게 내가 이해한 커스텀 훅이다.

커스텀 훅은 주로 인풋 태그를 관리하거나 fetch를 실행하는 데서 사용한다. (확실히 같은 로직이 여러 차례 반복되는 경우들이다.) 오늘은 직접 작성해 본 Custom Hook들을 기록해두려고 한다.

useInput 🤳🏻

우리가 리액트에서 인풋을 관리한다고 하면 그 로직은 대체로 비슷하다.

1) useState를 통해 인풋에 입력되는 value를 관리할 상태를 선언해준다.
2) 온 체인지에 setValue를 실행하는 함수를 할당해, value를 갱신해준다.

여러 개의 인풋을 관리해야 한다면, 위 로직을 여러 차례 반복해야 할 것이다. 우리는 커스텀 훅을 이용해, 위 로직을 함수로 만들고 재사용할 수 있다.

useFetch 📤

서버에 요청을 보내 데이터를 가져오는 코드도 대체로 우리는 비슷한 로직을 활용한다.

1) useState를 통해 서버의 응답에 담긴 데이터를 담을 상태를 선언해준다.
2) useEffect를 통해 서버에 데이터를 요청하고, 응답이 돌아오면 해당 데이터를 1) 단계에서 마련해둔 setter 함수를 통해 변수에 할당해준다.
3) 해당 상태를 활용한다.

App.js

import { useFetch } from "./useFetch";

function App() {
  const [hello] = useFetch("http://localhost:3001/hello", "loading...");
  const [bye] = useFetch("http://localhost:3001/bye", "loading...");

  return (
    <div className="App">
      <div>{hello}</div>
      <div>{bye}</div>
    </div>
  );
}

export default App;

useFetch.js

import axios from "axios";
import { useState, useEffect } from "react";

export const useFetch = (url, initialState) => {
  const [word, setWord] = useState(initialState);

  useEffect(() => {
    setTimeout(() => {
      axios.get(url).then((res) => setWord(res.data));
    }, 2000);
  }, [url]);

  return [word];
};

useAlert 🛎

useInputuseFetch는 흔히 많이 사용되는 커스텀 훅 예시라면, 또 다른 경우는 어떤 경우가 있을까 생각해보던 중, alert창을 만드는 로직을 커스텀 훅으로 분리해보기로 했다. 라인에서 작성한 커스텀 훅 관련 문서를 보다보니, 커스텀 훅에서도 JSX를 리턴할 수 있다는 사실을 알았다. 모쪼록 아래와 같은 useAlert라는 커스텀 훅을 작성해보았다.

jsx를 리턴하는 형태로 위와 같이 커스텀 훅을 작성하고 나니 궁금한 점은 그렇다면 커스텀 훅과 컴포넌트가 무엇이 다르냐는 점이다. (지금 당장 생각할 수 있는 건 props를 전달받지 않는다는 것 정도...?) 해당 부분을 고민해볼 과제로 남겨두고 우선 포스팅을 마무리한다.

profile
부정확한 정보나 잘못된 정보는 댓글로 알려주시면 빠르게 수정토록 하겠습니다, 감사합니다!

0개의 댓글