리액트 커스텀 훅에 대해서

Kim Jason·2023년 4월 2일
0

React Hooks

목록 보기
3/3
post-thumbnail

커스텀 훅

코드 및 로직의 반복을 최소화하고 재사용성을 높이기 위해 사용합니다.

커스텀 훅 안에 있는 상태와 effect는 커스텀 훅을 사용하는 컴포넌트 마다 독립적이다.
이러한 이유 덕분에 코드의 재사용성은 증가한다.
문제가 생기면 커스텀 훅 코드를 수정하면 되니까 디버깅도 쉬워진다.
자주 사용하는 useInput, useFetch 커스텀 훅을 예시로 들어보려 한다.

🧪 예시 1 (useInput)

// ✅ App.js

import { useState } from "react";

function App() {
  const [inputVal, setInputVal] = useState("");

  const handleChange = e => setInputVal(e.target.value);

  const handleSubmit = () => {
    setInputVal("");
    alert(inputVal);
  };

  return (
    <div>
      <h1>useInput</h1>
      <input value={inputVal} onChange={handleChange} />
      <button onClick={handleSubmit}>팝업</button>
    </div>
  );
}

export default App;

이렇게만 보면 문제가 없어 보인다.
하지만 input의 개수가 많아진다면 어떨까?
input 태그의 개수는 물론 각 태그에 대한 상태값과 handleChange 핸들러 함수를 모두 선언해줘야 한다.
중복 코드가 우후죽순 생겨날 뿐만 아니라 클린코드를 유지할 수 없는 불상사가 발생한다.

이때 커스텀 훅을 생성해서 문제를 해결할 수 있다.
useInput 커스텀 훅을 생성했고 App.js 코드를 보면 코드량이 감소한 걸 확인할 수 있다.

// ✅ useInput.js
import { useState } from "react";

export function useInput(initialVal, submitAction) {
  const [inputVal, setInputVal] = useState(initialVal);
  const handleChange = e => setInputVal(e.target.value);
  const handleSubmit = () => {
    setInputVal("");
    submitAction(inputVal);
  };

  return [inputVal, handleChange, handleSubmit];
}
// ✅ App.js
import { useInput } from "./useInput";

function displayPopup(content) {
  alert(content);
}

function App() {
  const [inputVal, handleChange, handleSubmit] = useInput("hi", displayPopup);

  return (
    <div>
      <h1>useInput</h1>
      <input value={inputVal} onChange={handleChange} />
      <button onClick={handleSubmit}>팝업</button>
    </div>
  );
}

export default App;

🧪 예시 2 (useFetch)

가상의 데이터를 불러오는 useFetch 커스텀 훅을 만들어보자.
fetchUrl 함수로 users, posts, todos 데이터를 불러올 수 있다.

// ✅ App.js

import { useEffect, useState } from "react";

const BASE_URL = "https://jsonplaceholder.typicode.com";

function App() {
  const [data, setData] = useState(null);

  const fetchUrl = type => {
    fetch(BASE_URL + "/" + type)
      .then(res => res.json())
      .then(setData);
  };

  useEffect(() => {
    fetchUrl("users");
  }, []);

  return (
    <div>
      <h1>useFetch</h1>
      <button onClick={() => fetchUrl("users")}>Users</button>
      <button onClick={() => fetchUrl("posts")}>Posts</button>
      <button onClick={() => fetchUrl("todos")}>Todos</button>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

export default App;

일단 리턴문 위로 지저분한 코드가 보인다.
코드의 재사용성도 높이고 클린코드를 유지하려면 어떡해야 할까?

이번에도 커스텀 훅을 사용함으로써 문제를 해결할 수 있다.
useFetch 커스텀 훅을 만들었고 App.js의 코드량이 감소했다.

// ✅ useFetch.js

import { useState, useEffect } from "react";

export function useFetch(baseUrl, initialType) {
  const [data, setData] = useState(null);

  const fetchUrl = type => {
    fetch(baseUrl + "/" + type)
      .then(res => res.json())
      .then(setData);
  };

  useEffect(() => {
    fetchUrl(initialType);
  }, []);

  return { data, fetchUrl };
}
// ✅ App.js

import { useFetch } from "./useFetch";

const BASE_URL = "https://jsonplaceholder.typicode.com";

function App() {
  const { data, fetchUrl } = useFetch(BASE_URL, "users");

  return (
    <div>
      <h1>useFetch</h1>
      <button onClick={() => fetchUrl("users")}>Users</button>
      <button onClick={() => fetchUrl("posts")}>Posts</button>
      <button onClick={() => fetchUrl("todos")}>Todos</button>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

export default App;
profile
성장지향형 프론트엔드 개발자

0개의 댓글