const useInput = (initialValue, vaildator) => {
const [value, setValue] = useState(initialValue);
const onChange = event => {
const {target:{value}}=event;
let willUpdate = true;
// function이 아닐경우를 막기 위해 - 없으면 function이 아닐 경우 에러발생함
if(typeof vaildator === "function") {
willUpdate = vaildator(value); // value가 있을 시 true;
}
if(willUpdate) {
setValue(value);
}
};
return {value, onChange};
};
function App() {
const max = value => value.length <= 10;
// or const notEmail = value => !value.includes("@"); => 값이 성립할 시 true, 안되면 false
const name = useInput("", max);
return(
<div>
<input {...name} />
</div>
);
}
// const content = [ { tab: ..., content: ... } ]
const useTabs = (initialTab, allTabs) => {
const [currentIndex, setCurrentIndex] = useState(initialTab);
if(!allTabs || !Array.isArray(allTabs) return;
// allTabs가 없거나 array가 아닌경우 return을 함으로써 에러 출력ㄴㄴ
return {
currentItem:allTabs[currentIndex],
changeItem:setCurrentIndex
};
};
function App() {
const {currentItem,changeItem} = useTabs(0, content);
return(
<>
{content.map((section, index) => {
<button onClick={()=>changeItem(index)}>{section.tab}</button>
}
<div>
<h1>{currentItem.contents}</h1>
</div>
</>
);
};
const useTitle = (initialTitle) => {
const [title, setTitle] = useState(initialTitle);
const updateTitle = () => {
const htmlTitle = document.querySelector("title");
htmlTitle.innerText = title;
}
useEffect(updateTitle, [title]);
return setTitle;
}
function App(){
const titleUpdate = useTitle("Loading...");
setTimeout(() => titleUpdate("Home"),3000);
// useTitle에서 setTitle을 반환하고 있으므로 titleUpdate = setTitle("Loading..")과 같은 뜻.
// titleUpdate("Home") = setTitle("Home") 과 같다. 참고로 Hook은 콜백함수안에서 호출이 안된다.
return(
<>
<h1></h1>
</>
);
};
const useClick = (onClick) => { // 인자로 onClick을 넘겨줌.
const ref = useRef(); // 현재속성을 나타내는 hook
useEffect(()=>{
// 1. 변수를 안에서 copy하지 않으면 warning (ref가 unmount 시점에 null이 된다.)
const element = ref.current;
if(element){
element.addEventListener("click",onClick);
}
return () => { // componentWillUnmount하는법.
if(element){
element.removeEventListener("click",onClick);
}
};
}, [onClick]);
return ref.current;
};
function App(){
const sayHi = () => console.log("say Hi"); // onClick 함수 설정.
const title = useClick(sayHi);
return(
<h1 ref={title}>Hi</h1> // useRef를 통해 클릭이벤트가 생길 요소에 ref={}를 작성.
)
};
useRef를 이용해 요소에 애니메이션 효과를 줄 수 있음.
const useFadeIn = (duration = 1, delay = 0) => { // duration과 delay에 기본값을 줌
const element = useRef();
useEffect(()=>{
if(element.current){
const {current}=element;
current.style.transition = `opacity ${duration}s else-in ${delay}s`
current.style.opacity = 1;
}
return {ref:element, style:{opacity:0}};
});
};
function App() {
const fadeInH1 = useFadeIn(1,2);
const fadeInP = useFadeIn(3,4);
return(
<div>
<h1 {...fadeInH1}>Hello</h1>
<p {...fadeInP}>lalalala</p>
</div>
);
}
사용자의 네트워크 (온라인, 오프라인)에 따라 실행됨.
const useNetwork = (onChange) => {
const [status, setStatus] = useState(navigator.onLine);
const handleOnchange = () => {
if(typeof onChange === "function"){
onchange(navigator.onLine);
};
setStatus(navigator.onLine);
};
useEffect(()=>{
window.addEventListener("online", handleOnchange);
window.addEventListener("offline", handleOnchange);
() => { // unmount될 때 이벤트 삭제를 위해 추가
window.removeEventListener("online", handleOnchange);
window.removeEventListener("offline", handleOnchange);
}
});
return status;
};
function App() {
const handleNetworkOnchange = (online) => {
console.log(online?"online":"offline");
}
const online = useNetwork(handleNetworkOnchange);
return(
<div>
<h1>{online ? "Online" : "Offline"}</h1>
</div>
);
};
scroll시 일어날 이벤트를 실행시킴
const useScroll = () => {
const [scroll, setScroll] =useState({ x:0, y:0 })
const onScroll = () => {
setScroll({ y:window.scrollY, x:window.scrollX })
}
useEffect(()=>{
window.addEventListener("scroll", onScroll);
return () => {
window.removeEventListener("scroll",onScroll);
}
}, []);
return statue;
};
function App(){
const { y } = useScroll();
return(
<div style={{height:1000vh}}>
<h1 style={{position:fixed, color: y > 100 ? "blue" : "red"}}>Hello</h1>
</div>
)
};
const useFullscreen = (callback) => {
const element = useRef();
const runCb = (isfull) => {
if (callback && typeof callback === "function") {
callback(isfull);
}
};
const triggerfull = () => {
const { current } = element;
if (current) {
// 크로스브라우징 때문에 전부 작성
if (current.requestFullscreen) {
current.requestFullscreen();
} else if (current.mozRequestFullscreen) {
current.mozRequestFullscreen();
} else if (current.webkitRequestFullscreen) {
current.webkitRequestFullscreen();
} else if (current.msRequestFullscreen) {
current.msRequestFullscreen();
}
}
runCb(true);
};
const exitFull = () => {
const checkFullScreen = document.fullscreenElement;
// esc로 나갈경우 에러발생 방지
if (checkFullScreen) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozExitFullscreen) {
document.mozExitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreenms();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
runCb(false);
}
};
return { element, triggerfull, exitFull };
};
function App() {
const onFulls = (isfull) => {
console.log(isfull ? "we are full" : "we are small");
};
const { element, triggerfull, exitFull } = useFullscreen(onFulls);
return (
<div>
<div ref={element}>
<img
alt="dog"
src="https://www.codeproject.com/KB/GDI-plus/ImageProcessing2/img.jpg"
/>
<button onClick={exitFull}>Exit</button>
</div>
<button onClick={triggerfull}>Full</button>
</div>
);
};
시스템 알람 설정을 할 수 있음
const useNotification = (title, options) => {
if(!("Notification" in window)){
return;
}
const fireNotif = () => {
// 알림 설정이 허가인 상태가 아닐 경우 허용창을 띄움 (한번만 띄움)
if(Notification.permission !== "granted") {
Notification.requestPermission().then(permission => {
if(permission === "granted"){
new Notification(title, options);
}else{
return;
}
});
}else {
new Notification(title, options);
}
};
return fireNotif;
};
function App() {
const triggerNotif = useNotification("let game start", { body: "nothing" });
return (
<div>
<button onClick={triggerNotif}>Hello</button>
</div>
);
}
axios를 통해 data를 fetch, refetch 할 수 있음
import defaultAxios from "axios";
const useAxios = (opts, axiosInstance = defaultAxios) => {
const [state, setState] = useState({ loading:true, error:null, data:null )}
const [trigger, setTrigger] = useState(0);
if(!opts.url)return;
const refetch = () => {
setState({ ...state, loading:true, })
setTrigger(Date.now()); // 랜덤숫자를 부여해 숫자가 부여될 때마다 refetch
}
useEffect(()=>{
axiosInstance(opts).then((data)=>{
setState({ ...state, loading:false, data });
}).catch((error)=>{
setState({ ...state, loading:false, error });
};
}, [trigger]);
return {...state, refetch};
};
function App() {
const { loading, error, data, refetch } = useAxios({
url: "fetch url"
});
console.log(
`Loading:${loading}\nError: ${error}\ndata:${JSON.stringify(data)}`
);
return (
<div>
<h1>{data && data.status}</h1>
<h2>{loading && "Loading..."}</h2>
<button onClick={refetch}>Hello</button>
</div>
);
}