[할일리스트]페이지전환과 스크롤 이벤트가 함께 발생할때 (useEffect에 클린업 함수를 써주어야한다.)->수정: useCallback함수를써준다-> 최종수정:React Router Hash Link

piper ·2024년 3월 7일
0

Project

목록 보기
9/15

어제 Link를 사용하여 메인페이지갔다가 스크롤되는 useCallback 함수를 만들었는데
랜더링 오류가 너무 많이 일어나고 일일이 고칠수가 없었다...
할 수 없이 구글링을 하니깐 라이브러리가 있었고 설명도 잘되어있어서 적용하여 사용하기로 했다.
구글링을 먼저 해 볼것을 했다.

https://www.npmjs.com/package/react-router-hash-link

적용한 코드예시:

  <Link to="/#mainSection"  // 여기엔 루트경로와 #을쓰고 엘리먼트의 아이디값을 적는다.
              scroll={() => {
                clickHeaderButton("mainSection"); //여기엔 스크롤되어서 갈 함수를 콜백함수로 !! 
              }}
            >
              Home
            </Link>
            
            

----------------React router hash link 라이브러리 사용전-----------------------

이제 이 작업을 마지막으로 마무리할 수 있을것 같다.
디테일 페이지의 헤더부분에서 Link를 통해 메인화면으로 갔다가 메인화면이 랜더링 되면 스크롤이동이
되는 페이지이다. 처음에는 그냥 순서대로 진행하면 될 것같아서
useEffect를 써주고 그 안에서 id의 값이 바뀌면 함수를 실행해주는 컴포넌트를 만들고
그 컴포넌트를 부모 컴포넌트로 만들고 {children} 이하에 오는 컴포넌트에 적용되게 해주었다.

import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";

const NavigationLink = ({ to, id, offset = 80, children }) => {
  const navigate = useNavigate();

  useEffect(() => {
    if (id) {
      const clickHeaderButton = (id, offset = 80) => {
        const section = document.getElementById(id);
        if (section) {
          const sectionPosition = section.offsetTop;
          window.scrollTo({
            top: sectionPosition - offset,
            behavior: "smooth",
          });
        }
      };
      clickHeaderButton(id, offset);
    }
  }, [id, offset]);

  const handleClick = () => {
    navigate(to);
  };

  return <span onClick={handleClick}>{children}</span>;
};

export default NavigationLink;

작동을 잘 되었다 !!! 성공인줄 알았지만 콘솔창을 보니
계속 하여 아래와 같은 에러가 발생하고 있었다.
Uncaught (in promise) Error: Extension context invalidated.
useEffect에 클린업을 하면 되지 않을까 싶어서 시도해보았다.
화면이 마운트 될 시에 값을 true로 해주고 언마운트 될때 false로 해주면
랜더링이 끝나고 화면이 언마운트 되면서 useEffect 내의 이벤트리스너 함수 실행이 종료된다.

import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";

const NavigationLink = ({ to, id, offset = 80, children }) => {
  const navigate = useNavigate();

  useEffect(() => {
    let isMounted = true;
    if (isMounted && id) {
      const clickHeaderButton = (id, offset = 80) => {
        const section = document.getElementById(id);
        if (section) {
          const sectionPosition = section.offsetTop;
          window.scrollTo({
            top: sectionPosition - offset,
            behavior: "smooth",
          });
        }
      };
      clickHeaderButton(id, offset);
    }
    return () => {
      isMounted = false;
    };
  }, [id, offset]);

  const handleClick = () => {
    navigate(to);
  };

  return <span onClick={handleClick}>{children}</span>;
};

export default NavigationLink;
profile
연습일지

0개의 댓글