커스텀 훅
코드 및 로직의 반복을 최소화하고 재사용성을 높이기 위해 사용합니다.
커스텀 훅 안에 있는 상태와 effect는 커스텀 훅을 사용하는 컴포넌트 마다 독립적이다.
이러한 이유 덕분에 코드의 재사용성은 증가한다.
문제가 생기면 커스텀 훅 코드를 수정하면 되니까 디버깅도 쉬워진다.
자주 사용하는 useInput, useFetch 커스텀 훅을 예시로 들어보려 한다.
// ✅ 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;
가상의 데이터를 불러오는 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;