[CustomHook]fetch, lockScroll, outsideClick

JH Cho·2022년 10월 2일
0

React

목록 보기
20/27

1. useLockBodyScroll

모달 창 활성화 시 마우스 스크롤로 인해서 모달창 뒤의 UI의 움직임을 방지

import { useLayoutEffect } from 'react';                    // 1

const useLockBodyScroll = () => {
  useLayoutEffect(() => {
    document.body.style.overflow = 'hidden';                // 2
    return () => {
      document.body.style.overflow = '';                    // 3
    };
  }, []);
};

export default useLockBodyScroll;
  1. useLayoutEffect :리액트 내장 훅으로 렌더링 후 실행되는 useEffect와 달리 렌더링 되기 전에 동작하는 훅.
  2. useLayoutEffect 내에서 body의 스타일이 overflow hidden이 되어 스크롤이 없어짐
  3. return(클린업이펙트)로 모달창이 닫히면 스타일을 복구

2. useOutsideClick

바깥 클릭하면 특정 동작을 하도록.

import { useState, useRef } from 'react';                              // 1
import useOnClickOutside from './useOnClickOutside.js'

const App = () => {
  const [isModalOpen, setModalOpen] = useState(false);                 // 2
  const ref = useRef();                                                // 3

  // 활용 예시
  useOnClickOutside(ref, () => setModalOpen(false));                   // 5

  return (
    <div className="backGround">
      {isModalOpen ? (
        <div ref={ref} className="modal">                              // 4
          👋 Hey, I'm a modal. Click anywhere outside of me to close.
        </div>
      ) : (
        <button onClick={() => setModalOpen(true)}>Open Modal</button>
      )}
    </div>
  );
}

export default App;
  1. useRef는 가상돔을 사용하는 리액트지만 특정 요소의 스크롤위치가 필요하거나 특정 요소에 포커스를 주는 등의 여러가지 상황에서 직접 DOM을 선택해야 하는 경우가 생길 때 사용함.

  2. useState 훅을 활용하여 모달창을 열고 닫을 수 있는 state 생성

  3. ref에 useRef 리턴값 할당.(ref을 설정해준 요소는 직접 DOM을 선택하여서 해당 요소의 여러 데이터 사용 가능)

  4. 모달창이 갖고 있는 데이터를 활용하기 위해서 모달창을 의미하는 modal 선택자에게 ref를 할당해줌. 이제 ref는 modal 선택자를 바라봄.

  5. useOnClickOutside 훅은 두 개의 인자를 받음. 첫 번째는 ref, 두 번째는 함수.

// Custom Hook이 Side Effect만 일으키고 return 값이 없으면
// 굳이 리턴 값을 정의해주지 않아도 됩니다!
import { useEffect } from 'react';

const useOnClickOutside = (ref, handler) => {                         
  useEffect(() => {
      const listener = (event) => {                                  
        if (!ref.current || ref.current.contains(event.target)) {     // 2
          return;
        }
        handler();                                                    // 3
      };

      document.addEventListener("mousedown", listener);               // 1
      return () => {
        document.removeEventListener("mousedown", listener);         
      };
    },

    [ref, handler]
  );
};

export default useOnClickOutside;
  1. 마우스를 누르는 순간 listener이벤트 발생
  2. listner 함수 내부 분기 처리
    : ref의 current 값이 true거나 ref의 current에 event.target이 있을 때는 return;
    모달창에서 이벤트가 발생하면 아무런 동작을 하지 않고 끝내겠다는 의미
  3. 두 가지 조건에 모두 충족하지 않으면 handler함수 호출
    : 모달창 닫힘

3. useFetch

서버에서 데이터를 주고 받기 위한 훅.

// useFetch.js

import { useState, useEffect } from "react";

const useFetch = (url) => {                                         // 1
  const [data, setData] = useState({});const [loading, setLoading] = useState(true);// 2
  const [error, setError] = useState("");const fetchResult = async () => {                                 // 3
    try {
      const response = await fetch(url);const json = await response.json();// 4
      setData(json);} catch (e) {
      setError(e);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchResult();
  }, [url]);

  return { loading: loading, data: data, error: error };
};

export default useFetch;
  1. useFetch는 url을 인자로 받음(API주소)
  2. 반환값 (data, loading, error)
  3. fetchResult함수는 서버에 데이터를 요청/응답하는 로직 처리
  4. fetch 메서드의 인자값으로 useFetch 훅에서 매개변수로 받은 url 넣어 줌. 이후 반환된 값을 response라는 변수에 담아주고 response를 json형태로 반환한 값을 jsond이라는 변수에 담음.
import React from 'react';
import useFetch from './useFetch.js';

const App = () => {
  const url = 'https://jsonplaceholder.typicode.com/posts';
  const { loading, data, error } = useFetch(url);

  return (
    <div>
      {data.map((list) => {
        return (
          <div key={list.id}>
            <h2>{list.title}</h2>
            <span>{list.body}</span>
          </div>
        );
      })}
    </div>
  );
};

export default App;

참고) data는 받아오는 중일 때는 undefined 리턴 함.

profile
주먹구구식은 버리고 Why & How를 고민하며 프로그래밍 하는 개발자가 되자!

0개의 댓글