ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React) 클릭하면 특정 div로 스크롤 이동하는 hook 만들어보기
    Web/React.JS 2022. 2. 27. 23:40

    지금 쇼핑몰 프로젝트를 하고 있는데 구현하고 싶은 기능이 있다.

     

     

    이렇게 생긴 버튼을 클릭하면 해당 부분으로 스크롤을 자동으로 움직여주는 기능이다.

    거의 모든 쇼핑몰에서 사용하고 있길래 이번 프로젝트에서 적용해 보았다.

     

    첨에는 쉽지 않겠다... 싶었는데

    찾아보니 useRef에 구현해놓은 메서드가 이미 존재했다

    (+  25.02.05 추가 : 과거 글 보다 추가 합니다 useRef가 아니라 useRef가 참조하는  HTMLDivElement에 존재합니다)

     

     (https://developer.mozilla.org/ko/docs/Web/API/Element/scrollIntoView)

    element.scroolIntoView라는 메서드였다.

     

    바로 useMoveScroll라는 hook을 만들어 활용해 보았다.

    import { useRef } from 'react';
    
    //hook
    function useMoveScrool() {
      const element = useRef<HTMLDivElement>(null);
      const onMoveToElement = () => {
        element.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
      };
      return { element, onMoveToElement};
    }
    
    export default useMoveScrool;

     

    behavior : 애니매이션을 사용할지 말지 선택함

    block : 클릭할시 어디에 사용자 스크롤을 위치시킬 건지 정함.

    "start""center""end""nearest"중 하나 선택. 기본값은 "start".

     

     

    cosnt {element, onMoveToElement} = useMoveScrool()
    
    return (
    <>
        <div onClick={onMoveToElement}>
            이걸 누르면?
        </div>
        <div ref={element}>
        	여기로 옵니다.
        </div>
    </>
    )

     

    실제로 작동하기는 한다.

     

    여기서 문제점은 만들 버튼이 3개가 있고 더 늘어날 수도 있다는 점이다.

    cosnt [element1, onMoveToElement1] = useMoveScrool()
    cosnt [element2, onMoveToElement2] = useMoveScrool()
    cosnt [element3, onMoveToElement3] = useMoveScrool()

    이런 식으로 하드코딩하는 건 피하고 싶어서

    hook을 배열처럼 사용하는 방법을 고민하다가

     

    https://izizi.tistory.com/28

     

    이 게시글에서 썻던 '유사 배열'을 사용하면 줄일 수 있지 않을까 생각이 돼서 적용해보았다.

     

      const goodsTabs = {
        0: useMoveScrool('상품 상세'),
        1: useMoveScrool('리뷰'),
        2: useMoveScrool('상품 문의'),
      };

    뭔가 해결되어가는 느낌이다.

    이제 hook을 배열로 만들어 주었으니

     

    goodsTabs[0].element
    goodsTabs[0].onMoveToElement

    element와 onMove 함수를 요런 식으로 사용할 수 있다.

     

     

    여기다가 map을 때려 박아서 컴포넌트를 만들면 끝이다 싶었는데 

    유사 배열에는 map가 없다...

     

    오류가 떳다.

     

    하드코딩을 피하려면 map를 반드시 사용해야 해서

    구글링을 해본 결과 유사 배열에 length 항목을 넣고

    Array.from()으로 유사 배열을 감싸주면 배열처럼 쓸 수 있다고 한다.

    https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/from

     

     

    결론

      const goodsTabs = {
        0: useMoveScrool('상품 상세'),
        1: useMoveScrool('리뷰'),
        2: useMoveScrool('상품 문의'),
        length: 3,
      };
    
    return (
        <>
          {Array.from(goodsTabs).map((tab, index) => {
            <div onClick={tab.onMoveToElement}>{tab.name}</div>;
          })}
          
              
          <div ref={goodsTabs[0].element}>
        	상품 상세
          </div>
        
          <div ref={goodsTabs[1].element}>
        	리뷰
          </div>
        
          <div ref={goodsTabs[2].element}>
        	상품문의
          </div>
       </>
    )

     

    이 hook은 두고두고 잘 써먹을 거 같다.

     

Designed by Tistory.