[TIL] Custom Hooks - 3

Mustache 🥸·2021년 7월 11일
0

React

목록 보기
6/6
post-custom-banner

https://velog.io/@devpark_0x1c/TIL-Custom-Hooks-2

에 이어 3번째 hooks 글을 써본다.

useFadeIn

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;

useScroll

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;

useNotification

notification을 활용한 hooks이다

https://developer.mozilla.org/ko/docs/Web/API/notification

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;

useAxios

프로젝트를 할 때 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을 하면서 적용해볼 생각이다.

post-custom-banner

0개의 댓글