티스토리 뷰

커스텀 훅을 쓰는 이유

자주 사용하는 로직을 하나로 묶어 반복을 최대한 줄이고 재사용하기 위해서 사용한다. 

 

 

useTitle

커스텀 훅을 만들 땐 똑같이 use~로 시작하는 함수를 선언한다. 넘겨받을 인자가 있다면 넘겨주면 된다. 커스텀 훅을 만들 때도 useState나 useEffect와 같은 리액트 훅을 사용할 수 있다. 컴포넌트에 전달하는 값이 아닌 커스텀 훅은 바로 실행시켜서 사용할 수 있다.

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 = () => {
  useTitle("Welcome");
  return <h1>Welcome</h1>;
}

 

 

useTabs

커스텀 훅에서 받아오는 인자가 원하는 타입이 맞는지 검증하고 아니면 종료시켜 아무 일도 발생하지 않도록 예외처리를 해주는 것이 좋다. 커스텀 훅이 여러 개를 리턴해야 한다면 객체 형태로 써줄 수 있고 사용하는 컴포넌트에서 구조 분해 할당을 할 수 있다.

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"
  }
];

const useTabs = (initialTab, allTabs) => {
  if (!allTabs || !Array.isArray(allTabs)) {
    return;
  }
  const [currentIndex, setCurrentIndex] = useState(initialTab);
  return {
    currentItem: allTabs[currentIndex],
    changeItem: setCurrentIndex
  };
};

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

 

 

useScroll

useEffect를 이용해서 addEventListener를 사용할 때는 잊지 않고 removeEventListener를 사용해서 이벤트를 지워준다.

const useScroll = () => {
  const [state, setState] = useState({
    x: 0,
    y: 0
  });
  const onScroll = () => {
    setState({ y: window.scrollY, x: window.scrollX });
  };
  useEffect(() => {
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return state;
};

const App = () => {
  const { x, y } = useScroll();
  return (
    <h1>
      We are in: {x} / {y}
    </h1>
  );
}

 

useInput

커스텀 훅이 여러개를 리턴하고 그것들을 한 요소에서 다 사용할 때 저렇게 {...name.props}를 사용해서 한 번에 넣어 줄 수 있다. onChange도 이름이 같다면 onChange 이벤트로 적용되는 것 같다...🤔

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 { props: { value, onChange }, utils: { setValue } };
};

const App = () => {
  const validator = value => !value.includes("@");
  const name = useInput("Mr. ", validator);
  return (
    <div className="App">
      <h1>Hello</h1>
      <input placeholder="Name" {...name.props} />
    </div>
  );
};

 

 

useFadeIn

커스텀 훅안에서 useRef를 사용해서 요소를 조작할 수도 있다. 아까의 onChang처럼 style도 이름이 동일해서 원래의 style처럼 작동하는 것 같다..🤔

const useFadeIn = (duration = 1, delay = 0) => {
  if (typeof duration !== "number" || typeof delay !== "number") {
    return;
  }
  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;
    }
  }, []);
  return { ref: element, style: { opacity: 0 } };
};

const App = () => {
  const fadeIn = useFadeIn(5, 10);
  return <h1 {...fadeIn}>This will fade in.</h1>;
}

 

 

useAxios

defaultAxios에 옵션을 넣어 요청을 보낼 수 있다. defaultAxios는 axios.create([config])의 리턴값을 말하는 걸까..? 🤔 원래 url의 키값은 baseURL인데 React에서는 url을 사용하기 때문에 옵션을 넣어서 사용하면 큰 문제없이 작동하는 것 같다.

import defaultAxios from "axios";
import { useState, useEffect } from "react";

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());
  };
  useEffect(() => {
    axiosInstance(opts)
      .then(data => {
        setState({
          ...state,
          loading: false,
          data
        });
      })
      .catch(error => {
        setState({ ...state, loading: false, error });
      });
  }, [trigger]);
  return { ...state, refetch };
};

const App = () => {
  const { loading, data, error, refetch } = useAxios({url : 'api주소'},)
  return (
    <div>
      <h1>{data && data.status}</h1>
      <h1>{loading && 'loading'}</h1>
      <button onClick={refetch}></button>
    </div>
  );
}

 

 

addEventListener에 쓸 수 있는 새롭게 알게 된 이벤트

beforeunload 이벤트

해당 창이나 문서가 언로드 될 때 발생하는 이벤트이다. 사용자가 페이지를 떠날 때 정말 떠날지 묻는 대화 상자를 트리거 할 수 있다.

event.returnValue에 메세지를 담아 함께 사용해주어야 한다.

 

online 이벤트

네트워크에 연결되어 navigator.onLine가 true가 되면 발생하는 이벤트이다.

 

offline 이벤트

네트워크에 연결되지 않아 navigator.onLine가 false가 되면 발생하는 이벤트이다.

 

 

Notification API

페이지의 바깥에 브라우저 알림을 띄울 수 있는 기능이다. 유저가 허락하여 granted상태일 때만 알림을 띄울 수 있다. 브라우저에 알림 기능이 있는지 먼저 확인해야 한다. 있다면 requestPermission 메소드로 알림 허락 요청을 보낼 수 있다.

  // Let's check if the browser supports notifications
  if (!('Notification' in window)) {
    console.log("This browser does not support notifications.");
  } else if (checkNotificationPromise()) {
    Notification.requestPermission().then((permission) => {
      handlePermission(permission);
    });
  } else {
    Notification.requestPermission((permission) => {
      handlePermission(permission);
    });
  }

 

유저가 허락하면 new Notification 객체에 옵션을 넣어 생성하여 알림을 보낼 수 있다.

const img = '/to-do-notifications/img/icon-128.png';
const text = `HEY! Your task "${title}" is now overdue.`;
const notification = new Notification('To do list', { body: text, icon: img });

 

 

Element.requestFullscreen()

요소를 풀 스크린으로 만드는 비동기 함수이다. 브라우저마다 메소드 이름이 달라서 확인해줘야 한다.

element.requestFullscreen() // 표준
element.webkitRequestFullscreen() // 크롬,사파리,오페라
element.mozRequestFullScreen() // 파이어폭스
element.msRequestFullscreen() // IE,Edge

 

Document.exitFullscreen()

풀 스크린을 종료하는 함수이다. 프로미스 객체를 반환하는 것을 보니 이 메소드도 비동기함수인 것 같다. 브라우저마다 메소드 이름이 달라서 확인해줘야 한다.

document.exitFullscreen() // 표준
document.webkitCancelFullscreen() // 크롬,사파리, 오페라
document.mozCancelFullScreen() // 파이어폭스
document.msExitFullscreen() // IE,Edge

 

Document.fullscreenElement

요소가 풀 스크린인지 아닌지 판단한다. 풀스크린 요소가 있으면 해당 요소를 반환하고 아니면 null을 반환한다.

document.fullscreenElement // 표준
document.webkitIsFullScreen // 크롬,사파리,오페라
document.mozFullScreen // 파이어폭스
document.msFullscreenElement // IE,Edge
728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함