210702 React Hooks TIL

Yang⭐·2021년 7월 2일
0

React

목록 보기
6/8

Custom Hooks 만들기

useInput

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>
  );
}

useTab

// 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>
  </>
  );
};

useTitle

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>
    </>
  );
};

useClick

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={}를 작성.
    )
};

useFadeIn

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>
  );
}

useNetwork

사용자의 네트워크 (온라인, 오프라인)에 따라 실행됨.

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>
  );
};

useScroll

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>
  )
};

useFullscreen

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>
  );
};

useNotification

시스템 알람 설정을 할 수 있음

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>
  );
}

useAxios

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>
  );
}

0개의 댓글

관련 채용 정보