[React] Hide Header when scroll down (ft.throttle)

raverana96·2022년 2월 23일
0

react

목록 보기
24/28

구현 사항

scroll을 아래로 내릴 때, header가 안보이게 되어야 한다. scroll을 위로 하면, header가 다시 보여야 한다.

코드

// page





const Page = () => {

  	// scroll이 일어나는 container. 현재 scroll 내린 만큼의 값을 구하기 위해
	const scrollContainerRef = useRef(null)
    // 과거의 scroll 값 저장 위해서
    const scrollRef = useRef(0)
    
    
      // 현재 scrollTop 지정
  useEffect(() => {
    if (scrollContainerRef.current) {
      scrollRef.current = scrollContainerRef.current.scrollTop;
    }
  }, [scrollContainerRef.current]);
    
    const handleScroll = () => {
    	const prevScroll = scrollRef.current;
        // scrollTop : distance from the element's top to its topmost visible content
      	const currentScroll = e.target.scrollTop;
      
      	if(prevScroll > currentScroll){
             console.log('go down')
        } else {
        	console.log('go up')
        }
      	// 현재 값을 넣어서 다음 scroll handle에서 이전 값으로 쓰게
        scrollRef.current = currentScroll;
    }
  
  

	return (
    	<PageContainer onScroll={handleScroll} ref={scrollContainerRef} >
      		<></>
        </PageContainer>
    );
}

go down, go up에서 state true, false를 정해주어서 header의 표시를 정해주면 된다.

throttle

위 코드로도 작동은 잘 하지만, 조금의 scroll event에도 마치 발작하듯이 무수히 많은 console.log의 요청(?)이 쏟아질 것이다. lodash 라이브러리의 throttle 함수를 사용해서 이를 조금 줄여보려고 한다.

throttle : 'n초에 한 번 작동'의 개념으로 받아들이면 이해가 쉽다.

  1. 먼저 handleScroll안의 로직 부분을 따로 분리하여 throttle을 걸어주려고 한다.

const handleScroll = () => {
    	const prevScroll = scrollRef.current;
      	const currentScroll = e.target.scrollTop;
      
  		/* 이부분을 들어내줄 것이다 */
      	if(prevScroll > currentScroll){
             console.log('go down')
        } else {
        	console.log('go up')
        }
        scrollRef.current = currentScroll;
   		/* 이부분을 들어내줄 것이다 */
    }
  1. useMemo를 사용해서 throttle을 건 함수를 만들어준다. (굳이 useMemo가 아니더라도 상관없을 것 같다. 그냥 함수여도 되고, useCallback을 사용해도 괜찮을 것 같다.)
  const throttledScroll = useMemo(
    (prevScroll, currentScroll) =>
      throttle((prevScroll, currentScroll) => {
        if (prevScroll > currentScroll) {
          //console.log('go down');
          setHide(() => false);
        } else {
          //console.log('go up');
          setHide(() => true);
        }
        scrollRef.current = currentScroll;
      }, 200),
    [],
  );


  const handleScroll = e => {
    const prevScroll = scrollRef.current;
    const currentScroll = e.target.scrollTop;

    throttledScroll(prevScroll, currentScroll);
  };
  • throttle안에 함수가 () => 들어가야한다는 것만 계속 인지하면 쉽게 해결할 수 있는 문제였다.

참고

https://www.w3schools.com/howto/howto_js_navbar_hide_scroll.asp

profile
더 나은 서비스를 고민하는 프론트엔드 개발자.

0개의 댓글