Custom Hook
ํ์ต ํค์๋
Custom Hook
Hook์ ๊ท์น
usehooks-ts
useBoolean
useCounter
useEffectOnce
useFetch
SWR
React-Query
useInterval
useEventListener
useLocalStorage
useDarkMode
๐ Custom Hook
์ปดํฌ๋ํธ ๋ก์ง์ ํจ์๋ก ๋ฝ์๋ด์ด ์ฌ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ
React์ State์ Lifecycle ๊ด๋ฆฌ ๋ก์ง์ ๊ณตํตํ ํ ์ ์๋๋ก ๋์์ฃผ๋ ์ญํ (์ปดํฌ๋ํธ๊ฐ์ ๋ก์ง ๊ณต์ )
๐ค Custom hook ์ฌ์ฉ๋ฒ
use
๋ก ์์ํด์ผ ํ๊ณ PascalCase๋ก ์ด๋ฆ์ ์์ฑํ๋ค.๐
hooks
ํด๋๋ฅผ ์์ฑํ๊ณ ํ๋์ ํ์ผ๋ก ๋ถ๋ฆฌ ํ ์ฌ์ฉ
๐ Hook์ ๊ท์น
1. ์ต์์(at the Top Level)์์๋ง Hook์ ํธ์ถํด์ผ ํ๋ค
๋ฐ๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ํน์ ์ค์ฒฉ๋ ํจ์ ๋ด์์ Hook์ ํธ์ถํ์ง ์๋๋ค.
// ์ฒ์์๋ ์ฝ๋ฐฑ ํจ์๋ ์กฐ๊ฑด๋ฌธ ์์์ Hook์ ํธ์ถํ๋ ์ค์๋ฅผ ํ๊ฒ ๋๋ค.
// Bad!!
if (playing) {
const products = useFetchProducts();
console.log(products);
}
2. React ํจ์ ๋ด์์ Hook์ ํธ์ถํด์ผ ํ๋ค
React ํจ์ ์ปดํฌ๋ํธ์์ Hook์ ํธ์ถ
Custom Hook์์ Hook์ ํธ์ถ
๐ usehooks-ts๋?
Hook ๋ผ์ด๋ธ๋ฌ๋ฆฌ
Hook์ ์ด๋ป๊ฒ ๋ง๋ค์๋์ง ์ฝ๋๋ฅผ ๋ณผ ์ ์๊ณ Custom Hook์ ๋ง๋๋๋ฐ ์๊ฐ์ ์ป์ ์ ์๋ค.
usehooks-ts ์ค์น
npm i usehooks-ts
โ๏ธ useBoolean
์ฐธ/๊ฑฐ์ง์ ๋ค๋ฃฐ ๋ toggle ๊ฐ์ด ์๋๊ฐ ๋ช ํํ ํจ์๋ฅผ ์ฐ๋ ๊ฒ ์ข๋ค.
import { useState } from 'react';
import { useBoolean } from 'usehooks-ts';
export default function Toggle() {
const [stateToggle, setStateToggle] = useState(false);
const { value: myToggle, toggle: myToggleFun } = useBoolean(false);
// setStateToggle(!stateToggle) ๋ณด๋ค toggle ํน์ myToggleFun์ด ์๋๊ฐ ๋ช
ํํ๋ค.
const handleState = () => {
setStateToggle(!stateToggle);
};
return (
<div>
<p> useState : {stateToggle ? 'True' : 'False'}</p>
<p> useBoolean : {myToggle ? 'True' : 'False'}</p>
<button type="button" onClick={handleState}>
useState hook ํ ๊ธ ๋ฒํผ
</button>
<button type="button" onClick={myToggleFun}>
useBoolean hook ํ ๊ธ ๋ฒํผ
</button>
</div>
);
}
โ๏ธ useCounter
import { useCounter } from 'usehooks-ts'; // ์ฌ์ฉํด๋ณด๋,ํจ์ฌ ์ฝ๋์ ์๋๊ฐ ๋ช
ํํด์ง๊ณ ๊ฐ๊ฒฐํ๋ค.
export default function Toggle() {
const { count, increment } = useCounter(0);
return (
<div>
<p> useCounter : {count}</p>
<button type="button" onClick={increment}>
useCounter hook ๋ฒํผ
</button>
</div>
);
}
โ๏ธ useEffectOnce
์์กด์ฑ ๋ฐฐ์ด์ ๋น ๋ฐฐ์ด๋ก ๋ฃ์ด์ ํ ๋ฒ๋ง ์คํํ๋ Effect๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋ฐ useEffectOnce hook ์ด๋ฆ์์๋ถํฐ ์๋๊ฐ ๋ช ํํ ๋๋ฌ๋๋ค.
const [products, setProducts] = useState<Product[]>([]);
useEffectOnce(() => {
const fetchProducts = async () => {
const url = 'http://localhost:3000/products';
const response = await fetch(url);
const data = await response.json();
setProducts(data.products);
};
fetchProducts();
});
return products;
โ๏ธ useFetch
์ ๋ง ๊ฐ๋จํ ์ธ ๋ ์ข์, ๊ทธ๋ฌ๋ ๊ธฐ๋ฅ์ด ๋ง์ง ์๋ค.
export default function useFetchProducts() {
const url = 'http://localhost:3000/products';
const { data } = useFetch(url);
if (!data) {
return [];
}
return data.products;
}
๋ช ๊ฐ์ง ๊ธฐ๋ฅ์ด ์ด์ง ๋ ์๋ useFetch ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฐ๋ก ์๋ค. โ use-http (๋ง์ด ์ฌ์ฉํ์ง ์๋๋ค.)
์ฌ์ฉ๋ฒ์ด ๋ ๋ณต์กํค๋ ๊ด์ฐฎ๋ค๋ฉด, ์บ์ ์ด์๋ฅผ ๊ณ ๋ คํ๋ ๋ค๋ฅธ ๋์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ค.
SWR : ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ํ React Hooks
SWR์ ์ฌ์ฉํ๋ฉด ์ปดํฌ๋ํธ๋ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋ฐ๋์๋์ง ํ์ธํ๋ค. ์๋ฅผ ๋ค์ด, ๊ฒ์ํ์ด๋ฉด ๊ฒ์๋ฌผ์ด ์ฌ๋ผ์๋์ง ํ์ธํ๋ค. React Query๋ ์ด๋ณด๋ค ๋ ๋ณต์กํ ๊ฒ์ ๋ค๋ฃฐ ๋ ์ฌ์ฉํ๋ค.
โ๏ธ useInterval
React์์ setInterval ๋ฑ์ ์ธ ๋๋ ์ฃผ์ํด์ผ ํ ๋ถ๋ถ์ด ์์ด์ Custom Hook์ ๋ง๋ค์ด์ ํด๊ฒฐํด์ผ ํ๋ค.
ํด๋น Hook ์ฐ๊ธธ ์ถ์ฒํ๋ค! setInterval ์ด์๊ฐ ๋ถ๋ช ์ด ์๋ค.
useEffect๊ด์ โ Not Found(?)
โ๏ธ useEventListener
โญ๏ธ ๊ฐ๋ ฅ ์ถ์ฒ โญ๏ธ
๋ชจ๋ ์ข ๋ฅ์ ์ด๋ฒคํธ๋ฅผ ํ์ธํ ์ ์๋ค.
ํนํ dispatchEvent๋ก ์ ๋ฌ๋๋ ์ปค์คํ ์ด๋ฒคํธ์ ๋ฐ์ํ๊ธฐ ์ข๋ค.
โ๏ธ useLocalStorage
LocalStorage์ ๊ฐ์ฒด๋ฅผ ๋ฃ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ์ด์ ๊ฐ์ ๊ฒฝ์ฐ stringfy ์ parse๋ฅผ ์๋์ผ๋ก ํด์ค๋ค.
์ด๋ฒคํธ๋ฅผ ํตํด(dispatchEvent + useEventListener) ๋ค๋ฅธ ์ปดํฌ๋ํธ์ ๋๊ธฐํํ๋ ๊ฒ ๋งค์ฐ ์ค์ํ ํน์ง
โ๏ธ useDarkMode
os ์ด์์ฒด์ ์ ๋คํฌํ ๋ง๋ฅผ ํ์ฉํ๊ณ ์ถ์ ๋
โ๐ป Custom Hook, usehooks-ts ์ ๋ฆฌ
Custom Hook
์ ํ์ฉํ๋ค๋ฉด ์ฌ์ฌ์ฉ ์ธก๋ฉด์์ ๋ฆฌ์กํธ์ ๊ฐ์ ์ ์ ๋๋ก ์ฌ์ฉ ํ ์ ์๋ค. ์ฌ์ฌ์ฉ ํ ์ ์๋๋ก ๋ก์ง์ ์ ์๊ฐํด์ผ ํ ๊ฒ ๊ฐ๋ค.usehooks-ts
์ฐธ๊ณ ํ ๋ง ํ ๋ด์ฉ์ด ๋ง๊ณ , ํ์ฉ์ฑ ์ธก๋ฉด ์ผ์ด๋์ ์ถ์ฒํ๋ค.๋ณ๋ ์ค์น ์์ด ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ์ฌ์ฉํด๋ ์ข๊ณ , Custom Hook์ ํ์ฉ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ๋ง๊ธฐ ๋๋ฌธ์ ์์ฃผ ๋ณด๋ฉด์ ์๊ฐ์ ์ป์ ์ ์๋ค.
๐ ์ฐธ๊ณ
Last updated