❗문제상황
메인페이지에서 무한스크롤로 독서기록 피드를 보다가 특정 기록을 보고 다시 뒤로가기로 이동하면 메인페이지의 최상단으로 이동한다. 이는 사용자가 기존의 기록을 계속 볼 수 없고 다시 스크롤을 해야 하는 상황이어서 사용자 경험에 좋지 않아 개선되어야할 것 같다는 팀원들의 공통적인 의견이 있어 이를 해결해야할 필요가 있었다.
👩💻로컬스토리지에 스크롤 위치 저장하기
스크롤 위치를 저장하는 방법으로 리코일과 로컬 스토리지 중 고민하다가 로컬스토리지를 선택하였다.
로컬스토리지를 선택한 이유
사용자가 임의로 값을 변경하는 등의 경우를 최소화하기 위해서는 리코일이 좋지만 새로고침 시에도 다시 뒤로 돌아가면 스크롤 위치를 기억하게 하고 싶었다. 그래서 새로고침과 상관없이 데이터를 저장할 수 있는 로컬스토리지를 선택하였다.
또한 다른 페이지에서도 무한스크롤을 사용하기 때문에 재사용할 수 있도록 커스텀 훅으로 제작하고자 하였다.
🖱️스크롤 위치 기억하는 커스텀 훅 만들기
import { useState } from 'react';
const useRememberScroll = (key: string) => {
const [currentScroll, setCurrentScroll] = useState<number>(() => {
const saveScroll = localStorage.getItem(key);
return saveScroll ? JSON.parse(saveScroll) : 0;
});
const setScroll = () => {
const currentY = window.scrollY;
setCurrentScroll(currentY);
localStorage.setItem(key, JSON.stringify(currentY));
};
const resetScroll = () => {
setCurrentScroll(0);
localStorage.removeItem(key);
};
return { currentScroll, setScroll, resetScroll };
};
export default useRememberScroll;
커스텀 훅의 인자로 key값을 받아서 해당 key값을 로컬 스토리지에 저장하도록 하였다.
useState의 기본 값으로 key에 해당하는 값이 로컬스토리지에 있다면 가져오고 아니면 0 기본값을 설정하였다.
setScroll을 통해 현재 스크롤 위치를 useState 값과 로컬스토리지에 저장하는 역할을 한다.
resetScroll은 state의 값과 로컬스토리지의 값을 0으로 초기화한다.
📑setScroll로 스크롤 위치 저장하기
//FeedItem.tsx
const { setScroll } = useRememberScroll('mainFeed');
const handleMoveRecordFeed = () => {
if (!isAuthorized) {
openAuthRequiredModal();
return;
}
setScroll();
router.push({
pathname: 'book/feed',
query: {
recordId,
type: 'MAIN',
},
});
};
위의 코드는 특정 기록피드를 눌렀을 때 해당하는 기록페이지로 이동하는 부분이다. 이 부분에서 setScroll 호출함으로써 mainFeed 라는 이름의 key 값으로 현재 스크롤 위치를 저장한다.
//RecordFeedList.tsx
const { currentScroll, resetScroll } = useRememberScroll('mainFeed');
useEffect(() => {
if (currentScroll) {
window.scrollTo(0, Number(currentScroll));
resetScroll();
}
}, [currentScroll, resetScroll]);
스크롤을 이동한 컴포넌트에서 동일한 key 값을 사용할 수 있도록 동일한 문자열을 커스텀 훅에 넘겨준다.
만약 currentScroll이 있다면, 즉 0이 아니라면 해당 위치로 이동한 후 resset해준다.
resetScroll 해주는 이유는 피드를 보고 다시 메인페이지로 이동했을 때 스크롤 위치를 기억해두는데 기억된 상태에서 다른 페이지를 갈 경우 계속 스크롤 위치가 기억되어 있기 때문에 이전 스크롤 기억은 지우는 것이 좋을 것 같다고 생각하였다. 따라서 한번 이동한 후에는 reset하여 스크롤 기억을 초기화할 수 있도록 하였다!
마무리
로컬스토리지를 이용하니 간단하게 해결하였다. 해당 커스텀 훅을 꼭 무한스크롤에만 아니라 다른 곳에서도 활용할 수 있지 않을까라는 생각이 든다.
새롭게 알게 된 점은 JSON.parse, JSON.stringify 를 했을 때 원래의 값이 number라면 stringify를 하고 다시 parse를 하면 기존의 타입인 number로 돌아온다는 점이었다. 주로 객체 값에 사용했기 때문에 문자열로 변환되려나? 했는데 기존의 타입으로 변한되어서 타입을 일치시켜주기 편했던 것 같다.
'개발 공부 > React' 카테고리의 다른 글
[nextJS]일정 시간 이상 걸리는 페이지 이동만 로딩 처리 (0) | 2023.07.23 |
---|---|
[next + tanstack query] 낙관적 업데이트 적용하기 (0) | 2023.07.22 |
color-thief 라이브러리 type 지정하기 (0) | 2023.07.02 |
[프로젝트 고민]input 불필요한 렌더링 줄이기 (0) | 2023.04.15 |
[프로젝트 고민]useMutation에서 async/await 적용하기 (6) | 2023.03.30 |