13.Custom Hooks
Updated:
웹 사이트에서 자주 작동하는 기능들을 custom hooks 로 제작하여 yarn, npm 설치가 가능하도록 publish 하였습니다.
Hook | Description | Documentation | NPM Page | Yarn Page |
---|---|---|---|---|
useTitle | Update your document’s title. | Documentation | NPM Page | yarn Page |
useScroll | React Hook to get X/Y coordinates of current position of the scroll. | Documentation | NPM Page | yarn Page |
usePreventLeave | React Hook to prompt the user for confirmation before leaving the page. Useful when changes haven’t been saved. | Documentation | NPM Page | yarn Page |
useNetwork | React Hook to listen when the user goes online or offline. | Documentation | NPM Page | yarn Page |
useInput | React Hook to update input event | Documentation | NPM Page | yarn Page |
useHover | React Hook to detect a hover on an any React Element | Documentation | NPM Page | yarn Page |
useFadeIn | React Hook to fade in any element. | Documentation | NPM Page | yarn Page |
useConfirm | React Hook to ask the user for a confirmation before executing a function. | Documentation | NPM Page | yarn Page |
useClick | React Hook to execute a function when the mouse click then add event listener | Documentation | NPM Page | yarn Page |
useBeforeLeave | React Hook to execute a function when the mouse leaves the page. Useful to show a popup or for analytics. | Documentation | NPM Page | yarn Page |
useAxios | React Hook to send HTTP request and get data from URL | Documentation | NPM Page | yarn Page |
1.useTitle
-
인터넷 브라우저 창 위에 Title 을 변경하는 hooks
-
HTML Title 이 Loading… 이라고 mount 될때 실행되고 5초 후에 Home 으로 변경 시키는 useTitle 이용 예시
import React, { useEffect, useState } from "react";
import "./App.css";
// useTitle
const useTitle = (initialTitle) => {
const [title, setTitle] = useState(initialTitle);
const updateTitle = () => {
const htmlTitle = document.querySelector("title");
htmlTitle.innerText = title;
};
useEffect(updateTitle, [title]);
return setTitle;
};
const App = () => {
const titleUpdate = useTitle("Loading...");
setTimeout(() => titleUpdate("Home"), 5000);
return (
<div className="App">
<h1>Hello</h1>
</div>
);
};
export default App;
2.useScroll
- 유저가 스크롤 해서 무언가를 지나갈때 색상을 바꾸거나 무언가를 할 수 있게 만들어 주는 hooks
// useScroll
const useScroll = () => {
const [state, setState] = useState({
x: 0,
y: 0,
});
const onScroll = () => {
setState({ y: window.scrollY, x: window.scrollX });
};
useEffect(() => {
window.addEventListener("scroll", onScroll);
// cleanUp
return () => window.removeEventListener("scroll", onScroll);
}, []);
return state;
};
const App = () => {
const { y } = useScroll();
return (
<div className="App" style=>
<h1 style=>
Hello
</h1>
</div>
);
};
export default App;
3.usePreventLeave
-
보통 웹사이트에서 만약 window 창을 닫을때 “아직 저장 되지 않았어!” 라고 메세지를 보낸때 사용되는 hooks
-
또는 API 에 요청을 보냈는데 네트워크 속도가 느려서 아직 data 가 다 넘어 오지 않았는데 user 가 창을 닫거나 작업을 중단 시키려고 할때 작업이 다 끝나지 않았다로 알리는 message
const usePreventLeave = () => {
const listener = (e) => {
e.preventDefault();
e.returnValue = "";
};
const enablePrevent = () => window.addEventListener("beforeunload", listener);
const disenablePrevent = () =>
window.removeEventListener("beforeunload", listener);
return { enablePrevent, disenablePrevent };
};
const App = () => {
const { enablePrevent, disenablePrevent } = usePreventLeave();
return (
<div className="App">
<h1>Hello</h1>
<button onClick={enablePrevent}>Protect</button>
<button onClick={disenablePrevent}>Unprotected</button>
</div>
);
};
export default App;
4.useNetwork
- useNetwork 는 offline 으로 네트워크로 변경할때 메세지를 호출하는 hooks
const useNetwork = (onChange) => {
const [status, setStatus] = useState(navigator.onLine);
const handleChange = () => {
if (typeof onChange === "function") {
onChange(navigator.onLine);
}
setStatus(navigator.onLine);
};
useEffect(() => {
window.addEventListener("online", handleChange);
window.addEventListener("offline", handleChange);
// clean Up
return () => {
window.removeEventListener("online", handleChange);
window.removeEventListener("offline", handleChange);
};
}, []);
return status;
};
const App = () => {
const handleNetworkChange = (online) => {
console.log(online ? "We are in onLine" : "OffLine check network");
};
const OnLine = useNetwork(handleNetworkChange);
return (
<div className="App">
<h1>{OnLine ? "Online" : "Offline"}</h1>
</div>
);
};
export default App;
5.useInput
-
기본적으로 input 을 업데이트 하는 hooks
-
initialValue, validator 를 parameter 를 받아서 input 창에서 10개 이상의 글자를 쓸 수 없게 하는 custom hooks
// useInput
const useInput = (initialValue, validator) => {
const [value, setValue] = useState(initialValue);
const onChange = (e) => {
const {
target: { value },
} = e;
let willUpdate = true;
if (validator) {
willUpdate = validator(value);
}
if (willUpdate) {
setValue(value);
}
};
return { value, onChange };
};
const App = () => {
const maxLen = (value) => value.length <= 10;
const name = useInput("Mr.", maxLen);
return (
<div className="App">
<h1>Hello</h1>
<input placeholder="Name" {...name} />
</div>
);
};
6.useHover
- 마우스를 대상에 올려 놓게 되면 event 가 실행하는 hooks
// useClick
const useHover = (onHover) => {
const element = useRef();
useEffect(() => {
if (element.current) {
element.current.addEventListener("mouseenter", onHover);
}
// cleanUP
return () => {
if (element.current) {
element.current.addEventListener("mouseenter", onHover);
}
};
}, []);
if (typeof onHover !== "function") {
return;
}
return element;
};
const App = () => {
const sayHello = () => console.log("Say Hello");
const hover = useHover(sayHello);
return (
<div className="App">
<h1>Hello</h1>
<button ref={hover}>클릭</button>
</div>
);
};
export default App;
7.useFadeIn
- 요소에 fade in 효과를 주는 hooks
// useFadeIn
const useFadeIn = (duration = 1, delay = 0) => {
const element = useRef();
useEffect(() => {
if (element.current) {
const { current } = element;
current.style.transition = `opacity ${duration}s ease-in-out ${delay}s`;
current.style.opacity = 1;
}
}, []);
if (typeof duration !== "number" || typeof delay !== "number") {
return;
}
return { ref: element, style: { opacity: 0 } };
};
const App = () => {
const fadeInH1 = useFadeIn(1, 2);
const fadeInP = useFadeIn(5, 3);
return (
<div className="App">
<h1 {...fadeInH1}>Hello</h1>
<p {...fadeInP}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto
aperiam minus accusamus ratione, necessitatibus sapiente! Ut mollitia at
dolorum ea asperiores consectetur. Nostrum quo unde voluptates eveniet
aliquam! Atque, dignissimos?
</p>
</div>
);
};
export default App;
8.useConfirm
- 사용자가 무언가를 하기전에 확인하는건데 만약 사용자가 버튼을 클릭하는 작업을 하면 (이벤트를 실행하기 전에) 메세지를 보여주고 싶은것 (alert 창에 정말로 삭제 하시겠습니까? 같은 것)
// useConfirm
const useConfirm = (message = "", onConfirm, onCancel) => {
if (!onConfirm || typeof onConfirm !== "function") {
return;
}
if (!onCancel || typeof onCancel !== "function") {
return;
}
const confirmAction = () => {
if (window.confirm(message)) {
onConfirm();
} else {
onCancel();
}
};
return confirmAction;
};
const App = () => {
const deleteWorld = () => console.log("단어가 삭제되었습니다.");
const abort = () => console.log("삭제가 취소 되었습니다.");
const confirmDelete = useConfirm(
"정말로 삭제하시겠습니까?",
deleteWorld,
abort
);
return (
<div className="App">
<h1>Hello</h1>
<button onClick={confirmDelete}>Click me</button>
</div>
);
};
export default App;
9.useClick
- 마우스를 클릭하게 되면 event 가 실행하는 hooks
const useClick = (onClick) => {
const element = useRef();
useEffect(() => {
if (element.current) {
// 'click' is keyword
element.current.addEventListener("click", onClick);
}
// CleanUp ComponentWillUnmount()
return () => {
if (element.current) {
element.current.removeEventListener("click", onClick);
}
};
}, [onClick]);
if (typeof onClick !== "function") {
return;
}
return element;
};
const App = () => {
const sayHello = () => console.log("Say Hello");
const title = useClick(sayHello);
return (
<div className="App">
<h1 ref={title}>Hello</h1>
</div>
);
};
10.useBeforeLeave
- 기본적으로 탭을 닫을때 실행되는 function 팝업이나 특히 뭔가를 중지시키려고 할때 “나가지마요” 라고 라는 function 을 사용하는 hooks
// useBeforeLeave
const useBeforeLeave = (onBefore) => {
const handle = (e) => {
// clientY 마우스의 y 축의 위치 기준으로 0 보다 작은경우 함수 실행 (top 위치일때)
const { clientY } = e;
if (clientY <= 0) {
onBefore();
}
};
useEffect(() => {
document.addEventListener("mouseleave", handle);
// cleanUp
return () => document.removeEventListener("mouseleave", handle);
}, []);
if (typeof onBefore !== "function") {
return;
}
};
const App = () => {
const begForLife = () => console.log("Pls don't leave");
useBeforeLeave(begForLife);
return (
<div className="App">
<h1>Hello</h1>
</div>
);
};
export default App;
11.useAxios
- HTTP request 를 만드는 hooks
import React, { useEffect, useState } from "react";
import defaultAxios from "axios";
import "./App.css";
// useAxios
const useAxios = (opts, axiosInstance = defaultAxios) => {
const [state, setState] = useState({
loading: true,
error: null,
data: null,
});
const [trigger, setTrigger] = useState(0);
const refetch = () => {
setState({
...state,
loading: true,
});
setTrigger(Date.now());
};
useEffect(() => {
axiosInstance(opts)
.then((data) => {
setState({
...state,
loading: false,
data,
});
})
.catch((error) => {
setState({ ...state, loading: false, error });
});
}, [trigger]);
if (!opts.url) {
return;
}
return { ...state, refetch };
};
const App = () => {
const { loading, data, refetch } = useAxios({
url: "https://yts.mx/api/v2/list_movies.json",
});
return (
<>
<div className="App">
<h1>{data && data.status}</h1>
<h2>{loading && "Loading"}</h2>
<button onClick={refetch}>Refetch</button>
</div>
</>
);
};
export default App;
🔶 🔷 📌 🔑
Reference
- normad corder hooks - https://nomadcoders.co/react-hooks-introduction/lobby
Leave a comment