api 호출을 통해 생성된 특정 컴포넌트로 스크롤 이동을 구현.
useRef와 응답 데이터를 가공해 ref 배열을 만들고 이를 이용하여 특정 dom에 접근한다.
type DivRef = {
ref: HTMLDivElement | null;
};
type TGameListWithDateResponseDate = Pick<TGameListWithDate, 'date'>;
export type TGameListDateRef = TGameListWithDateResponseDate & DivRef;
// shedule.tsx
const scheduleListRef = useRef<TGameListDateRef[]>([]);
// shedule.tsx
sortedMonthlyGameList.map(({ games: gameList, date }, index) => (
<ScheduleContent
date={date}
gameList={gameList}
isHome={false}
key={index}
ref={(ref) => {
ref && scheduleListRef.current.push({ date, ref });
}}
/>
))
// ScheduleContent.tsx
const ScheduleContent = forwardRef<HTMLDivElement, ScheduleContentProps>(
({ gameList, date, isHome }, ref) => {
return (
<div
className="divide-y divide-border-and-divide overflow-hidden rounded-md border border-border-and-divide"
ref={ref}
>
...
</div>
);
},
);
ScheduleContent.displayName = 'ScheduleContent';
// schedule.tsx
useEffect(() => {
// 서버에서 가져온 데이터를 통해 만들어진 경기일정 컴포넌트의 ref를 이용.
// 오늘 날짜와 경기일정들의 date들을 비교 하여. 가장가까운 ref찾는다.
// 찾은 ref를 통해 스크롤을 이동시킨다.
const todayDate = getTodayDate();
if (selectedYearMonthDate.getMonth() !== todayDate.getMonth()) {
// 다른 날짜는 굳이 스크롤 할 필요 없어서 바로 리턴.
return;
}
if (scheduleListRef && scheduleListRef.current.length > 0) {
let targetRef: TGameListDateRef = scheduleListRef.current[0];
let dateDifference = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < scheduleListRef.current.length; i++) {
const currentRef = scheduleListRef.current[i];
if (currentRef.date === shortISO(todayDate)) {
// 같은 날짜면 더 볼 필요 없음
targetRef = currentRef;
break;
} else {
// 같은 날짜가 아니라면 차이가 제일 적은 날짜로 설정.
const tempDiff = Math.abs(new Date(currentRef.date).getTime() - todayDate.getTime());
if (dateDifference > tempDiff) {
targetRef = currentRef;
dateDifference = tempDiff;
}
}
}
targetRef.ref?.scrollIntoView({ behavior: 'smooth', block: 'center' });
// ref 초기화
scheduleListRef.current = [];
}
}, [gameList, gameListByTeamId, selectedYearMonthDate]);
useRef object배열로 관리하기 + 리팩토링:
https://80000coding.oopy.io/774fd94b-686d-4a95-aeab-b8f0a376f1c6
useRef 공식 문서 :
https://ko.react.dev/learn/manipulating-the-dom-with-refs#accessing-another-components-dom-nodes