에 이어 3번째 hooks 글을 써본다.
fadeIn 애니메이션 처리를 할 수 있는 hooks이다
import { useEffect, useRef } from "react";
const useFadeIn = (duration = 1, delay = 0) => {
// duration이 number가 아닐 경우 return
if (!typeof duration === "number") {
return;
}
const element = useRef();
useEffect(() => {
// 현재 hooks를 사용하는 태그에서 사용될 css 처리 아래와 같이 한다
if (element.current) {
const { current } = element;
current.style.transition = `opacity ${duration}s ease-in-out ${delay}s`;
current.style.opacity = 1;
}
}, []);
return { ref: element, style: { opacity: 0 } };
};
const App = () => {
// useFadeIn(지속시간, 지연시간)으로 사용된다
const fadeInH1 = useFadeIn(2, 3);
const fadeInP = useFadeIn(5, 10);
return (
<div>
<h1 {...fadeInH1}>miyoung</h1>
<p {...fadeInP}>ㅎ_ㅎ</p>
</div>
);
};
export default App;
scroll 위치에 따른 이벤트를 처리하는 hooks
import { useEffect, useState } from "react";
const useScroll = () => {
// scroll의 y축의 초기값을 설정해준다
const [scroll, setScroll] = useState({
y: 0
});
// scroll이 움직일 때마다 state의 y의 값을 변경한다
const handleScroll = () => {
setScroll({ y: window.scrollY });
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return scroll;
};
const App = () => {
const { y } = useScroll();
return (
<div style={{ height: "1000vh" }}>
// 스크롤의 y축이 100 이상일 경우 h1의 글씨 색상이 변경된다
<h1 style={{ position: "fixed", color: y > 100 ? "pink" : "black" }}>
Miyoung
</h1>
</div>
);
};
export default App;
notification을 활용한 hooks이다
const useNotification = (title, body) => {
// 이 부분은 notification의 mdn에 있는 것을 그대로 사용하였다
// 브라우저가 Notification을 지원하지 않으면 아래와 같은 경고가 나타난다
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
}
const fireNotification = () => {
// noti의 권한이 granted일 경우 매개변수로 넘어온 title, body를 사용하여 알림창이 나타난다
if (Notification.permission === "granted") {
new Notification(title, body);
// notification이 denied일 경우 권한 요청을 하고 granted로 변경되면 알림창이 나타난다
if (Notification.permission === "denied") {
Notification.requestPermission((permission) => {
if (permission === "granted") {
new Notification(title, body);
}
});
}
}
};
return fireNotification;
};
const App = () => {
// 알림창에 대한 내용을 선언한다
const notif = useNotification("빵 먹을까?", {
body: "미영이 빵 좋아해"
});
return (
<div style={{ height: "1000vh" }}>
// 버튼을 클릭할 경우 권한을 확인하고 위에서 설정한 알림 내용이 나타난다
<button onClick={notif}>Miyoung</button>
</div>
);
};
export default App;
프로젝트를 할 때 axios를 사용할 일이 굉장히 많았는데, 중첩되는 내용이 너무 많아서 hooks를 사용했으면 좋지 않았을까 하는 생각이 든다
import defaultAxios from "axios";
import { useEffect, useState } from "react";
const useAxios = (opts, axiosInstance = defaultAxios) => {
// state에 데이터가 불러오기 전까지 사용될 loading
// 수신된 데이터를 받아둘 data
// error 메세지를 받을 error를 선언한다
const [state, setState] = useState({
loading: true,
data: null,
error: null
});
// 다시 fetch할 때 사용할 trigger를 선언한다
const [trigger, setTrigger] = useState(0);
// fetch할 대상이 될 url이 없을 경우 return
if (!opts.url) {
return;
}
// reFetch는 아래에서 새로 받아올 데이터를 유지하고 trigger는 현재 시간을 설정해줌으로 새로 rendering을 한다.
const reFetch = () => {
setState({
...state,
loading: true
});
setTrigger(Date.now());
};
useEffect(() => {
// axios를 실행하고 데이터를 처리한다
// 다시 데이터를 받아올 trigger를 처리하기 위해 useEffect의 dependency는 trigger를 바라본다
axiosInstance(opts.url)
.then((data) => {
setState({
loading: false,
error: null,
data: JSON.stringify(data)
});
})
.catch((err) => {
setState({
loading: false,
err,
...state
});
});
}, [trigger]);
return { ...state, reFetch };
};
export default useAxios;
이번 hooks 공부를 마무리지으며 2차 프로젝트에 hooks를 적용할 부분이 있으면 refactoring을 하면서 적용해볼 생각이다.