[React] 넷플릭스 클론 코딩 (7)

노유성·2023년 5월 14일
0
post-thumbnail

⭐useDebounce custom hooks

🪐Debounce란?

기존에 우리가 만든 웹에서는 검색창에 검색어를 입력할 때마다 DB서버에게 axios 요청을 보낸다.
기능상에는 문제가 없지만 이렇게 되면은 단순히 검색에 너무나도 많은 자원이 사용되게 된다. 그런 이유로 우리는 Debounce를 사용한다. Debounce란 사용자가 미리 정해진 시간 동안 타이핑을 멈출 때까지 이벤트 처리를 지연시킨다. 이를 통해 API호출 수를 크게 줄일 수 있다.

🪐hooks 폴더 및 파일 생성


앞으로 우리가 custom hooks를 만들어서 사용할 때는 hooks 폴더를 만든 후에 해당 폴더 하위에 custom hooks를 만들어서 사용한다.

🪐useDebounce.js

export const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState("");

  useEffect(() => {
    const hanlder = setTimeout(() => {
      setDebouncedValue(value)
    },delay);
  
    return () => {
      clearTimeout(hanlder);
    }
  }, [value, delay])

  return debouncedValue;
}

인자로 사용자가 타이핑한 값과 기다릴 시간을 각각 value, delay로 받는다. 그 다음 setTimeout을 이용해서 비동기적으로 delay시간을 기다린 다음에 setter함수를 이요해서 value를 지정한다.

의존성 배열에 value, delay를 할당하고 해당 값이 변동되면은 return문에 해당하는 클린업 함수를 실행한다. 그리고 다시 작업을 수행한다.

왜 이렇게 구상을 했을까 라는 의문점이 들었다. 내가 봤을 때는 2가지 이유이다. 하나는 만약에 사용자가 입력창에 값을 입력하는 도중에 부모 컴포넌트 중 특정 state변수가 변동되면은 하위의 모든 컴포넌트는 리렌더링이 되는데 해당 경우에서 영향을 받지 않기 위해 useEffect()를 사용한 것 같다. 또 하나는 timer를 기다리다가 특정 이벤트가 발생하면 다시 reset하는 기능을 사용하는 데에 useEffect()의 clearup만한 것이 없기 때문에 useEffect hooks를 사용해서 custom hooks를 만든 것 같다.

url이 변경되면 query.get("q") 함수가 호출되어 useDebounce함수도 같이 호출되며 그때 인자로 넘어가는 searchTerm의 값이 이전과 다르다면 useDebounce의 useEffect()에 정의된 의존성 배열의 요소가 변경되므로 cleanup함수가 실행되고 새롭게 타이머가 작동한다.

🌠clearTimeout()

clearTimeout() 함수는 JavaScript에서 타이머를 취소하는 데 사용됩니다. 일정 시간 후에 실행되도록 예약된 타이머를 취소하여 실행되지 않도록 할 수 있습니다.
일반적으로 setTimeout() 함수를 사용하여 일정 시간 후에 실행되는 타이머를 생성할 수 있습니다. 그러나 경우에 따라 타이머를 중지하고 실행을 취소해야 할 수 있습니다. 이때 clearTimeout() 함수를 사용합니다.
-chatGPT

⭐상세 페이지 구현

searchPage에서 특정 영화를 클릭하면 상세 내용을 보여주는 페이지를 구현할 예정이다. 간단하게 해당 영화의 이미지를 가져와서 보여주는 것으로 구현하겠다.

🪐SearchPage/index.js


특정 이미지를 클릭하면은 상세 페이지를 보여주게 하는 이벤트 리스너를 등록한다.


기존에 App.js에서 라우트를 위와 같이 지정해놓았기 때문에 navigate함수를 이용해서 DetailPage를 보여줄 수 있게 구성한다.

movieId는 경로 매개변수이며 DetailPage는 매개 변수를 이용해서 클릭한 영화의 포스터를 보여줄 예정이다.

🪐DetailPage/index.js

export default function DetailPage() {
  const {movieId} = useParams()
  const [movie, setMovie] = useState({})
  useEffect(() => {
    async function fetchData() {
      const request = await axios.get(
        `/movie/${movieId}`
      )
      setMovie(request.data);
    }
    fetchData();
  }, [movieId])
  
  if (!movie) return <div>...loading</div>;

  return (
    <section>
      <img
        className="modal__poster-img"
        src={`https://image.tmdb.org/t/p/original/${movie.backdrop_path}`}
        alt="poster"
      />
    </section>
  );
}

🌠useParams()

경로 매개변수로 지정한 값을 가져올 수 있는 hooks이다. 객체를 반환하며 property로 라우트에서 지정한 매개변수가 들어있으며 해당 값으로 매개 변수의 값이 있다.

🌠useEffect()

movieId가 바뀔 때 즉, useParams()로 가져오는 값이 바뀔 때, 다시 말해서 사용자가 클릭한 이미지가 바뀔 때 함수가 실행된다.

axios를 통해서 movieId의 이미지를 받아와서 화면에 보여준다. 의존성 배열의 요소인 movieId가 없애도 현재로써는 동작을 잘하지만 react에서 생명주기를 아직 정확히 잘 모르기도 하고 나중에 movieId를 detailpage에서 바꿀 수 있을 때(새로운 포스터를 클릭하는 요소가 있을 때)에는 의존성 배열의 요소로 movieId를 지정한 것이 의미가 있을 것 같다.

⭐모달 창 외부 클릭시 모달 닫기 기능


위 사진에서 모달창 외부를 클릭하면 모달창을 닫게하는 기능을 구현하겠다. useRef를 이용해서 구현할 예정이다.

🪐useRef란?

useRef는 React의 훅 중 하나로, 값을 기억하고 업데이트할 수 있는 변수를 생성하는 데 사용됩니다. useRef는 함수형 컴포넌트에서 가변적인 상태를 유지하거나 DOM 요소에 접근하는 데 사용될 수 있습니다.
useRef를 사용하여 생성된 변수는 컴포넌트의 생명주기 동안 유지되며, 해당 변수의 값이 변경되어도 컴포넌트가 리렌더링되지 않습니다. 이는 useRef가 생성한 변수를 사용하여 컴포넌트 외부의 상태를 저장할 수 있다는 의미입니다.
-chatGPT

기능을 구현하기 위해서 useRef는 특정 dom요소를 지정하는데에 사용된다. useRef를 통해서 만든 ref객체를 통해서 특정 dom 요소의 상태 및 정보를 알 수 있다.

🌠컴포넌트 종류별 사용법

🌠DOM을 직접 선택해야 하는 경우

🪐hooks/useOnClickOutside.js

export default function useOnCLickOutside(ref, handler) {
  useEffect(() => {
    const listener = (event) => {
      if(!ref.current || ref.current.contains(event.target)) return;
      handler();
    }
    document.addEventListener("mousedown", listener);

    return () => {
      document.removeEventListener("mousedown", listener);
    }
  }, [])
}

ref 객체와 핸들러를 인자로 받아서 사용하는 custom hooks이다. 바깥은 클릭하면은 모달창을 제거하기 위해서 사용된다. ref.current는 ref객체를 가지고 있는 dom 요소의 html 소스코드이다. lister 함수는 이벤트를 받아서 ref.current가 존재하는지 또 이벤트 타겟을 ref가 포함하는지의 여부를 파악한다. 만약에 존재한다면 hooks를 종료하고 아닐 시에는 인자로 받은 handler를 실행한다.

useEffect를 이용해 문서 객체 전체 즉, 현재 웹페이지 DOM 최상위 요소에 이벤트 리스너를 등록한다. 그리고 cleanup 함수에서 이벤트 리스너를 제거한다.

🪐MovieModal/index.js


기존의 모달창에 ref객체를 선언하고 useOnClickOutside hooks를 호출한다. useOnClickOutside hooks에서 사용할 hanlder로 Modal창을 열 것인지 닫을 것인지의 여부를 나타내는 flag state 변수의 setter함수를 넘겨준다. 외부를 클릭하면은 모달창을 닫을 것이기 때문에 hooks에서 사용할 handler 함수는 false 값을 할당하는 setter이다.

profile
풀스택개발자가되고싶습니다:)

0개의 댓글