Custom Hooks... ๐ตโ ... ๊ณต๋ถํ๋ฉด์ ์ ๊ฒ ๊ฐ์ผ๋ฉด์๋ ์ด๋ ค์ด ๊ฒ ๊ฐ๋ค.
์ฌ์ดํธ์์ ํน์ ์์๊ฐ ๋ํ๋๋ ํจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์ํ Hooks์ด๋ค. ์ ์ฌํ ๋ฐฉ์์ผ๋ก Fade Out Hooks๋ ๋ง๋ค์ด ๋ณผ ์ ์์ ๊ฒ ๊ฐ๋ค.
const useFadeIn = (duration = 1, delay = 0) => {
const element = useRef();
// ํ์ด๋์ธ ํจ๊ณผ๋ฅผ ์ค ์์๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด useRef๋ฅผ ์ฌ์ฉํ๋ค.
useEffect(() => {
const { current } = element;
current.style.transition = `opacity ${duration}s ease-in-out ${delay}s`;
current.style.opacity = 1;
}, []);
// duration(ํจ๊ณผ ์งํ์๊ฐ)๊ณผ delay(ํจ๊ณผ ์ง์ฐ์๊ฐ)์ ์ธ์๋ก ๋ฐ๋๋ค.
// ์์์ ๋ฃ์ ํจ๊ณผ๋ฅผ componentDidMount๋ก ์ ์ํ๋ค.
return { ref: element, style: { opacity: 0 } };
// ์์์ ์ธ๋ผ์ธ์ผ๋ก ๋ฃ์ ์์ฑ์ ๋ฆฌํดํ๋ค.
// opacity๋ก ํ์ด๋์ธ ํจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์ํด ์ด๊ธฐ๊ฐ์ผ๋ก opacity ๊ฐ์ 0์ผ๋ก ์ค๋ค.
};
// ์ฌ์ฉ ์์
const App = () => {
const handleH = useFadeIn(2, 1);
const handleP = useFadeIn(5, 3);
return (
<div>
<h1 {...handleH}>Hello</h1>
<p {...handleP}>welcome to my home!</p>
</div>
);
};
์ฌ์ฉ์๊ฐ ์ ์ํ ๋คํธ์ํฌ ํ๊ฒฝ์ด ์จ๋ผ์ธ์ธ์ง ์คํ๋ผ์ธ์ธ์ง์ ๋ฐ๋ผ ํน์ ํจ์๋ฅผ ์คํํ ์ ์๋ Hooks์ด๋ค.
const useNetwork = (onChange) => {
const [status, setStatus] = useState(navigator.onLine);
// ์จ๋ผ์ธ๊ณผ ์คํ๋ผ์ธ์ผ ๋์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ค.
const handleNetwork = () => {
if (typeof onChange === "function") {
onChange(navigator.onLine);
}
setStatus(navigator.onLine);
};
useEffect(() => {
window.addEventListener("online", handleNetwork);
window.addEventListener("offline", handleNetwork);
return () => {
window.removeEventListener("online", handleNetwork);
window.removeEventListener("offline", handleNetwork);
};
}, []);
// ์ด๋ฒคํธ๋ฆฌ์ค๋๋ก ์จ๋ผ์ธ๊ณผ ์คํ๋ผ์ธ์ผ ๋ ๊ฐ๊ฐ ์ธ์๋ก ๋์ด์ค๋ ํจ์๋ฅผ ์คํํ ์ ์๋๋ก ํ๋ค.
return status;
};
// ์ฌ์ฉ ์์
const App = () => {
const checkStatus = (isOnline) => console.log(isOnline ? "yes" : "no");
// useNetwork Hooks๋ฅผ ํตํด ์คํ๋๋ ํจ์์ด๋ค.
const onLine = useNetwork(checkStatus);
return (
<div>
<h1>{onLine ? "Online" : "Offline"}</h1>
// ์จ๋ผ์ธ, ์คํ๋ผ์ธ ์ํ์ ๋ฐ๋ผ ํ
์คํธ๋ฅผ ๋
ธ์ถํ๋ค.
</div>
);
};
ํ์ด๋์ธ/์์๊ณผ ๋๋ถ์ด ์น ํ์ด์ง์์ ์์ฃผ ์ฌ์ฉ๋๋ ํจ๊ณผ์ธ ์คํฌ๋กค ์ด๋ฒคํธ๋ฅผ Hooks๋ก ๋ง๋ค์๋ค.
const useScroll = () => {
const [scrollState, setScrollState] = useState({
x: 0,
y: 0
});
// ์ด๋ฒคํธ์ x, y์ขํ์ ์ํ๋ฅผ ๊ด๋ฆฌํ์ฌ ์ด๋ฒคํธ๋ฅผ ์คํํ๋ค.
const handleScroll = () => {
setScrollState({ x: window.scrollX, y: window.scrollY });
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
// ์คํฌ๋กค ์ด๋ฒคํธ๊ฐ ์์ ๋๋ง๋ค ์ด๋ฒคํธ๊ฐ ์คํ๋๋ค.
return scrollState;
};
const App = () => {
const { y } = useScroll();
return (
<div style={{ height: "1000vh" }}>
<h1 style={{ position: "fixed", color: y > 100 ? "red" : "green" }}>
// useScroll๋ก ์ด๋ฒคํธ๋ฅผ ์คํํ๋ y ๊ฐ์ ๋ฐ๋ผ ์ปฌ๋ฌ๊ฐ ๋ณ๊ฒฝ๋๋ค.
Hello
</h1>
</div>
);
};
ํน์ ์ด๋ฒคํธ์์ ์๋ฆผ์ด ์ค๋๋ก ํ๋ Hooksd์ด๋ค. ์ด Hooks๋ฅผ ์ฐ์ตํ๋ฉด์ MDN์ด ์ผ๋ง๋ ์น์ ํ์ง ๋ค์ ํ ๋ฒ ๋๊ผ๋ค. ๐
const useNotification = (title, options) => {
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
}
// ํด๋น ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฆผ์ ์ง์ํ๊ณ ์๋์ง ์ฌ๋ถ๋ฅผ ๊ฐ์ฅ ๋จผ์ ํ์ธํ๋ค.
const getNotice = () => {
if (Notification.permission === "granted") {
new Notification(title, options);
if (Notification.permission !== "denied") {
Notification.requestPermission((permission) => {
if (permission === "granted") {
new Notification(title, options);
}
});
}
}
// ์ฌ์ฉ์์ ์๋ฆผ ํ์ฉ ์ํ์ ๋ง์ถฐ ์๋ฆผ์ ๋ณด๋ด๊ฑฐ๋ ์๋ฆผ ํ์ฉ์ ์์ฒญํ๋ค.
};
return getNotice;
};
// ์ฌ์ฉ ์์
const App = () => {
const handleNotice = useNotification("warning", { body: "JW loves you" });
return (
<div>
<button onClick={handleNotice}>Click!</button>
</div>
);
};
์์ฝ๋์์ ํ ๋ฌ๊ฐ ์งํํ๋ 2๋ฒ์ ํ๋ก์ ํธ์์ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ผ๋ฉฐ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋๋ฐ, ๊ทธ ๋๋ง๋ค ๋๋ fetch๋ฅผ ์ฌ์ฉํ์๋ค. ๊ทธ๋์ ํ๋ก์ ํธ ๋ฆฌํฉํ ๋ง์์ fetchํ๋ ๋ถ๋ถ์ axios๋ก ๋ณํํ๊ธฐ ์ํด Axios๋ฅผ custom Hooks๋ก ๋ง๋ค์ด ๋ณด์๋ค!
axios ์ค์น
npm i axios
App.js
import useAxios from './useAxios';
const App = () => {
const { Loading, data, refetch } = useAxios({
url: "https://yts.mx/api/v2/list_movies.json"
});
return (
<div>
<div>{Loading && "Loading..."}</div>
<div>{data && data}</div>
<button onClick={refetch}>Refetch!</button>
</div>
);
};
useAxios.js
import defaultAxios from "axios";
import { useState, useEffect } from "react";
const useAxios = (opts, axiosInstance = defaultAxios) => {
const [state, setState] = useState({
Loading: true,
data: false,
error: false
});
// ๋ก๋ฉ, ๋ฐ์ดํฐ, ์๋ฌ ๊ฐ ์ํ ์ด๊ธฐ๊ฐ์ ์ค์ ํ๋ค.
const [trigger, setTrigger] = useState(0);
const refetch = () => {
setState({
...state,
Loading: true
});
setTrigger(Date.now());
};
// re-fetch๋ฅผ ์ํ ๋ฒํผ ํด๋ฆญ ์ ๋ก๋ฉ ์ํ๋ฅผ true๋ก ๋ณ๊ฒฝํ๋ค.
// useEffect๋ฅผ ์คํํ๊ธฐ ์ํ trigger์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋๋ก Date ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
useEffect(() => {
axiosInstance(opts)
.then((res) => setState({ ...state, Loading: false, data: res.status }))
.catch((error) => {
setState({ ...state, Loading: true, error: error });
});
}, [trigger]);
// ์ธ์๋ก ์ ๋ฌ๋ฐ์ url์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๋ณด์ฌ์ค๋ค.
// trigger๊ฐ ๋ณํ๋ ๋๋ง๋ค ๋ค์ fetch๋ฅผ ์งํํ๋ค.
return { ...state, refetch };
};
export default useAxios;