import { useState } from "react"
export const useInput = (initialValue, validator)=>{
const [value, setValue] = useState(initialValue);
const onChange = (event)=>{
const {
target: {value}
} = event;
let willUpdate = true;
if(typeof validator === "function"){
willUpdate = validator(value);
}
if(willUpdate){
setValue(value);
}
}
return { value, onChange };
};
const maxLen = value => !value.includes("@");
const name = useInput("Mr.", maxLen);
변수 선언 후 useInput(초깃값, 조건함수)
import { useState } from "react";
export const useTabs = (initialTab, allTabs)=>{
const [currentIndex, setCurrentIndex] = useState(initialTab);
if(!allTabs || !Array.isArray(allTabs)){
return;
}
return {
currentItem: allTabs[currentIndex],
changeItem: setCurrentIndex
};
};
const content =[
{
tab: "Section 1",
content: "I'm the content of the Section 1"
},
{
tab: "Section 2",
content: "I'm the content of the Section 2"
}
]
function App() {
const {currentItem, changeItem} = useTabs(0, content);
return (
<div className="App">
{content.map((section, index)=>(
<button onClick={()=> changeItem(index)}>{section.tab}</button>
))}
<div>{currentItem.content}</div>
</div>
);
}
const {currentItem, changeItem} = useTabs(0, content);
변수 선언후 useTabs(초기인덱스,배열)
함수안에 changeItem(인덱스)으로 이벤트 실행시 변경될 탭을 지정할 수 있다.
currentItem을 이용해 지정된 탭의 내용을 뿌려줄 수 있다.
import { useEffect, useState } from "react"
export const useTitle = initialTitle => {
const [title, setTitle] = useState(initialTitle);
const updateTitle = ()=>{
const htmlTitle = document.querySelector("title");
htmlTitle.innerText = title;
};
useEffect(updateTitle, [title]);
return setTitle;
}
const titleUpdater = useTitle("");
<div onClick={()=>{titleUpdater("타이틀명")}}>click</div>
변수에 useTitle()을 사용하여 onClick과 같은 액션시 변수의 매개변수로 변경할 타이틀 명을 넣어주어 사용한다.
import { useEffect, useRef } from "react";
export const useClick = (onClick)=>{
const element = useRef();
useEffect(()=>{
if(typeof onClick !=="function"){
return;
}
if(element.current){
element.current.addEventListener("click", onClick);
}
return ()=>{
if(element.current){
element.current.removeEventListener("click", onClick);
}
}
},[])
return typeof onClick !== "function"? undefined: element;
}
const hello = useClick(()=>{console.log("say hello")})
<h1 ref={hello}>Hi</h1>
변수에 useClick 사용 후 적용할 요소에 ref에 변수명을 적어서 사용
export 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 {
try{
onCancel();
} catch(error){
return;
}
}
}
return confirmAction;
}
const trueFunction = ()=>{console.log("확인입니다.")}
const falseFuntion = ()=>{console.log("취소입니다.)}
const confirmClick = useConfirm("질문",trueFunction,falseFunction)
변수에 useConfirm 사용 후 첫번째 매개변수로 질문, 두번째 매개변수로 true일 시 함수,
세번째 매개변수로 false일 시 함수를 넣어준다.
export const usePreventLeave = ()=>{
const listener = (event)=>{
event.preventDefault();
event.returnValue = "";
}
const enablePrevent = ()=>window.addEventListener("beforeunload", listener)
const disablePrevent = ()=>
window.removeEventListener("beforeunload", listener);
return { enablePrevent, disablePrevent };
}
const {enablePrevent, disablePrevent} = usePreventLeave();
<button onClick={enablePrevent}>protect</button>
<button onClick={disablePrevent}>unprotect</button>
const {enablePrevent, disablePrevent} = usePreventLeave()
선언 후 onClick이벤트에 같은 변수명으로 넣어준다
const {enablePrevent:변수명1, disablePrevent:변수명2} = usePreventLeave();
<button onClick={변수명1}>protect</button>
<button onClick={변수명2}>unprotect</button>
위와 같이 변수명을 변경하여 사용가능
import { useEffect } from 'react';
export const useBeforeLeave = (onBefore)=>{
useEffect(()=>{
document.addEventListener("mouseleave", handle)
return ()=> document.removeEventListener("mouseleave", handle)
},[])
if(typeof onBefore !=="function"){
return;
}
const handle = (event)=>{
//마우스가 클라이언트Y가 0보다 작아질때 useBeforeLeave의 매개변수 onBefore을 실행
const {clientY} = event;
if(clientY <= 0){
onBefore();
}
};
}
const useBeforeLeaveFunction = ()=> console.log("leaving");
useBeforeLeave(useBeforeLeaveFunction);
함수 생성 후 useBeforeLeave(함수명)으로 useBeforeLeave를 실행
import { useEffect, useRef } from 'react';
export 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 fadeInH1 = useFadeIn();
변수를 지정하고 값에 useFadeIn()을 넣는다.
사용하고자 하는 요소에 전개연산자를 활용하여 변수를 넣어준다.
<h1 {...fadeInH1}>안녕하세요.</h1>
import { useEffect, useState } from 'react';
export 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);
return ()=>{
window.removeEventListener("online", handleChange);
window.removeEventListener("offline", handleChange);
}
},[])
return status;
}
const onLine = useNetwork();
변수를 선언하고 값에 useNetwork()를 사용한다.
if(online){
console.log("we just went online")
}else{
console.log("we are offline")
}
useNetwork()의 매개변수에 useNetwork(handleNetworkChange)와같이 다른함수를 사용하여
온라인일 경우 함수를 실행할 수 있다.
import { useEffect, useState } from 'react';
export const useScroll = ()=>{
const [state, setState] = useState({
x:0,
y:0
});
const onScroll = ()=>{
//스크롤의 위치가 바뀔 때마다 state의 x와 y의 값을 변경
setState({y: window.scrollY, x: window.scrollX})
console.log("y ", window.scrollY, "x ", window.scrollX);
}
useEffect(()=>{
window.addEventListener("scroll", onScroll);
return ()=> window.removeEventListener("scroll", onScroll)
},[])
return state;
}
const {x,y} = useScroll();
위와 같이 변수 선언 후
<h1 style={{color: y> 100 ? "red" : "blue"}}>HI</h1>
x혹은 y의 값에 따라 변경되는 조건문을 사용해준다.
import { useRef } from 'react';
export const useFullscreen = (callback)=>{
const element = useRef();
const runCb = isFull => {
if(callback && typeof callback === "function"){
callback(isFull)
}
}
const triggerFull = ()=>{
if(element.current){
if(element.current.requestFullscreen){
element.current.requestFullscreen();
}else if(element.current.mozRequestFullscreen){
element.current.mozRequestFullScreen();
}else if(element.current.webkitRequestFullscreen){
element.current.webkitRequestFullscreen();
}else if(element.current.msRequestFullscreen){
element.current.msRequestFullscreen();
}
runCb(true);
}
}
const exitFull = ()=>{
document.exitFullscreen();
if(element.current){
if(element.current.requestFullscreen){
element.current.requestFullscreen();
}else if(element.current.mozRequestFullscreen){
element.current.mozRequestFullScreen();
}else if(element.current.webkitRequestFullscreen){
element.current.webkitRequestFullscreen();
}else if(element.current.msRequestFullscreen){
element.current.msRequestFullscreen();
}
runCb(false);
}
}
return {element, triggerFull, exitFull};
}
const onFullS = (isFull) => console.log(isFull ? "We are full" : "We are small");
const {element, triggerFull, exitFull} = useFullscreen(onFullS);
풀스크린을 할 대상에 ref={element}를 넣어주고
온클릭이벤트로 풀스크린 버튼에 triggerFull을, 종료버튼에 exitFull을 넣어준다
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;
}
const triggerNotif = useNotification("Hello", {body:"Nice to meet you",requireInteraction:true})
<button onClick={triggerNotif}>button</button>
변수 선언 후 이벤트에 변수를 넣어사용한다
useNotification(타이틀명, {프로퍼티명:값})
notification API를 이용한 Hook
notification 관련 정보는 아래 링크에서 확인 가능
https://developer.mozilla.org/ko/docs/Web/API/notification
import defaultAxios from "axios";
import { useEffect } from "react";
import { useState } from "react";
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};
}
export default useAxios;
const { loading, data, error, refetch } = useAxios({
url:"https://yts.mx/api/v2/list_movies.json"
});
위와같이 변수 선언 후 useAxios({url:주소})로 데이터를 받아온다