-
Notifications
You must be signed in to change notification settings - Fork 1
페이지가 렌더링 된 후 스크롤을 최상단으로 올리기
랜딩 페이지나 이벤트 페이지의 경우 화면에 위아래로 길고, 스크롤을 내릴때마다 해당 위치 컴포넌트들이 나타나는 스크롤 애니메이션이 적용되어야하는 스펙이었다. 이때 중간에서 새로고침을 하면 해당 위치에서 새로고침이 되는 것보다는 맨 첫 위치로 이동해서 다시 스크롤 애니메이션을 볼 수 있도록 하는 것이 더 자연스러운 UX라고 생각했다.
그래서 렌더링이 될 때마다 scroll을 top으로 끌어올리는 hook을 만들어서 스크롤 애니메이션이 들어가는 페이지마다 선언을 해주려고 했다.
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function useScrollTop() {
const { pathname } = useLocation();
useEffect(() => {
window.scroll({ top: 0 });
}, [pathname]);
}
useEffect
를 사용해서 첫 렌더링 시 / 새로고침 시 / pathname이 바뀔 시 스크롤을 맨 처음으로 올리도록 hook을 구현했다.
그런데 이 코드는 동작하지 않는다. 디버깅을 해보면 코드가 호출되기는 하는데 결정적으로 scroll이 top: 0
의 위치로 이동하지 않는다. 화면이 다 로드되지 않고 실행되서 그런가 싶어서 load 이벤트와 함께 동작하게 수정했다.
-
load
이벤트 : 페이지의 모든 요소(HTML, CSS, JavaScript, 이미지 등)가 완전히 로드된 후 발생한다
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function useScrollTop() {
const { pathname } = useLocation();
useEffect(() => {
const handleScroll = () => {
window.scroll({ top: 0 });
};
handleScroll();
window.addEventListener("load", handleScroll);
return () => {
window.removeEventListener("load", handleScroll);
};
}, [pathname]);
}
useEffect
내에서 load 이벤트 리스너를 부착해서, 자원이 모두 로드되었을 때 스크롤 top 이벤트가 발생할 수 있도록 했다.
그런데 여전히 실행 안된다. 그래서 좀 찾아보니 load
이벤트에서 scroll
을 호출할 때, 자원은 모두 로드되었을지라도 페이지가 완전히 렌더링되지 않았거나 브라우저의 최적화 과정 중에 있기 때문에, 스크롤 위치가 즉시 업데이트되지 않을 수 있다고 한다.
-
beforeunload
이벤트 : 페이지가 언로드되기 전에 발생한다
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function useScrollTop() {
const { pathname } = useLocation();
useEffect(() => {
const handleScroll = () => {
window.scroll({ top: 0 });
};
handleScroll();
window.addEventListener("beforeunload", handleScroll);
return () => {
window.removeEventListener("beforeunload", handleScroll);
};
}, [pathname]);
}
beforeunload
이벤트는 페이지가 완전히 렌더링된 상태에서 호출된다. 기존에 load
이벤트를 사용하는 경우에는 렌더링을 하고 스크롤을 top으로 올려주려고 했다면, beforeunload
의 경우 리렌더링 전 스크롤을 위로 올린 후 리렌더링이 된다. 그래서 스크롤 위치 조정이 올바르게 반영되고 다음 렌더가 실행돼서 원하는 대로 동작한다.
추가로 찾아보다가 알게된 history API(웹 브라우저의 세션 기록을 조작하고 관리할 수 있는 JavaScript API)의 속성인데, 새로고침 시 스크롤의 위치를 어떻게 할 것인가에 대한 결정을 하는 속성이다.
- "auto": 디폴트 값으로 페이지의 이전 스크롤 위치를 자동으로 복원한다
- "manual": 스크롤 위치를 자동으로 복원하지 않는다
이 속성을 manual
로 설정하면 원하는 대로 동작하지 않을까 했는데, 이 API는 새로고침 시(페이지 전체가 새로 로드)에만 동작하고 react-router-dom
의 Link 태그로 SPA 라우팅이 발생했을 때는 동작하지 않는다. 그래서 이 속성을 사용하지는 못하고 위에서 정의한 hook을 사용했다.
- 페이지가 렌더링 된 후 스크롤을 최상단으로 올리기
- DOM을 이미지로 저장하기
- Context API에서 불필요한 리렌더링을 줄이는 방법
- 무한 Transition 애니메이션
- Github Action 워크플로우 정의하기
- 무한 Transition 애니메이션 최적화하기
- 무한 Transition 애니메이션 최적화하기 2
- 무한 Transition 애니메이션 최적화하기 3
- fetch timeout 구현하기
- ErrorBoundary 구현하기
- 뒤로가기 confirm 로직 구현하기
- 선착순 밸런스 게임 상태 관리
- Modal 내부 컴포넌트에서 무한 스크롤이 제대로 동작 안되는 문제
- useToggleContents 훅 기본값 설정 및 조건부 사용법
- 폰트 굵기 적용 이슈
- SVG 내부 stroke 속성 값 제어를 위한 SVGIcon Util 함수 및 SVGR 사용 과정
- tailwindCSS의 @apply를 cva로 바꾸기
- 스크롤 내려갈 때 해당 섹션의 요소들 인터렉션 동작
- 공통 컴포넌트 내부에 애니메이션을 넣는 것에 대한 고민
- 특정 컴포넌트 위치에서 헤더 스타일 다르게 적용하는 방법
- 스크롤 거꾸로 올릴 때 IntersectionObserver가 뷰포트 감지 못하는 현상
- 선착순 밸런스 게임 최종 결과 계산에 대한 고민 (08.14)
- 프로그래스바 공통 컴포넌트로 분리
- (08.23 기준) 선착순 서버 시간 연동 문제
- 게임 종료된 상태에서 사용자 게임 참여 여부에 따른 FinalResult 분기 처리
- FinalResult 컴포넌트의 “당신의 선택” 카테고리 설정 이슈
- 게임 접속 시 게임 현재 진행 상태 초기화 및 카운트 다운 설정
- 선착순 밸런스 게임 UX 개선