Custom hook은 React에서 사용되는 함수이다.
React의 기본 훅인 useState, useEffect, useContext 등과 마찬가지로, Custom hook은 use
라는 접두사로 시작해야한다. 이는 React가 이 함수가 훅으로 사용되는 것을 인식할 수 있도록 한다.
Custom hook은 일반 JavaScript 함수이며, 다음과 같은 목적으로 사용될 수 있다.
1. 상태 로직 추상화
컴포넌트 간에 공유되는 상태와 관련된 로직을 추출하여 재사용할 수 있다. 이를 통해 코드 중복을 줄이고, 관심사를 분리하여 코드를 더 읽기 쉽고 관리하기 쉽게 만들 수 있다.
import { useState } from 'react';
function useInput(initialValue) {
const [value, setValue] = useState(initialValue);
const handleChange = event => {
setValue(event.target.value);
};
return [value, handleChange];
}
// 사용 예시
function MyComponent() {
const [name, setName] = useInput('');
return (
<input
type="text"
value={name}
onChange={setName}
/>
);
}
2. 생명주기 메서드 추상화
생명주기 메서드와 관련된 로직을 추상화하여 재사용할 수 있다. 예를 들어, 컴포넌트가 마운트될 때 데이터를 불러오는 로직을 custom hook으로 작성하면 다른 컴포넌트에서 해당 로직을 재사용할 수 있다.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch(url);
const result = await response.json();
setData(result);
};
fetchData();
}, [url]);
return data;
}
// 사용 예시
function MyComponent() {
const data = useFetch('https://api.example.com/data');
if (data === null) {
return <div>Loading...</div>;
}
return (
<div>
{data.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
3. 외부 라이브러리 통합
외부 라이브러리와의 상호 작용을 추상화하여 사용하기 쉽게 만들 수 있다. 예를 들어, ReactRouter를 사용하는 컴포넌트에서 라우팅 관련 로직을 custom hook으로 추출할 수 있다.
import React from 'react';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';
// Custom Hook: useRouting
function useRouting() {
const navigateTo = (path) => {
window.history.pushState(null, null, path);
window.dispatchEvent(new PopStateEvent('popstate'));
};
return { navigateTo };
}
// 사용 예시
function Home() {
const { navigateTo } = useRouting();
return (
<div>
<h1>Home</h1>
<button onClick={() => navigateTo('/about')}>Go to About</button>
</div>
);
}
function About() {
const { navigateTo } = useRouting();
return (
<div>
<h1>About</h1>
<button onClick={() => navigateTo('/home')}>Go to Home</button>
</div>
);
}
function App() {
return (
<BrowserRouter>
<nav>
<ul>
<li>
<Link to="/home">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
</Switch>
</BrowserRouter>
);
}
export default App;