상황 설명
1.
운동 라이브러리와 같은 UI상에서 각 카테고리별로 스크롤이 따로 움직이도록 작업 (BUR-3956)
2.
카테고리별로 스크롤 위치를 기억하게 하는것으로 구현하고자함
3.
리액트 네이티브 자체적으로 사용하는 flatlist는 문제 없이 구현됐지만, draggable flatlist에 동일한 방법을 적용할 경우 스크롤 위치가 계속 어긋나는 이슈가 생김 (+ 퍼포먼스 저하)
Flatlist 구현 코드
•
ExerciseLibraryScreen.tsx에 스크롤 위치 저장
const listRef = useRef(null);
const scrollPositions = useRef({}); // 각 카테고리별 스크롤 위치 저장용
// 스크롤 할때마다 스크롤 위치 저장
const handleScroll = (event) => {
scrollPositions.current[filteredResult?.bId] = event.nativeEvent.contentOffset.y;
};
// 카테고리 변경 시 해당 카테고리에 맞는 스크롤 위치 적용
const handleBodyPartChange = (bId) => {
requestAnimationFrame(() => {
const y = scrollPositions.current[bId] || 0;
listRef.current?.scrollToOffset({ offset: y, animated: false });
});
};
JavaScript
복사
•
ManageExerciseList.tsx (flatlist가 있는 컴포넌트)
<View style={{ flex: 1, paddingHorizontal: 16 }}>
<FlatList
// scroll ref값 (prop으로 전달 받음)
ref={listRef}
bounces
windowSize={5}
showsVerticalScrollIndicator
data={listData}
keyExtractor={(item) => `${item.eId.toString()}`}
renderItem={({ item }) => (
<ExerciseLibraryListItem
eId={item.eId}
eTextId={item.eTextId}
bId={item.bId}
eName={item.eName}
eInfoType={item.eInfoType}
tId={item.tId}
cnt={item?.cnt}
drag={null}
tooltip={tooltip}
setTooltip={setTooltip}
isKeyboardVisible={isKeyboardVisible}
/>
)}
// 스크롤 할때마다 스크롤 위치 저장 (prop으로 전달 받음)
onScroll={handleScroll}
ListFooterComponent={() => <View style={{ height: 120 }} />}
keyboardShouldPersistTaps='always'
/>
</View>
JavaScript
복사
•
BodyParSelector.tsx (카테고리 변경용 컴포넌트)
{exerciseBodyPart.map((bItem) => (
<View key={bItem.bId} style={{ minWidth: 56 }}>
<TouchableOpacity
hitSlop={{ top: 8, right: 8, bottom: 8, left: 8 }}
onPress={() => {
if (handleBodyPartChange) {
// 카테고리 변경 시, 저장되어있던 스크롤 위치 적용 (prop으로 전달 받음)
handleBodyPartChange(bItem.bId);
}
filterExerciseByBodypart(bItem.bId);
}}
style={bId === bItem.bId ? styles.buttonSelected : styles.buttonNormal}
>
<BFText name='B3' lightColor={bId === bItem.bId ? BFCOLOR.WHITE : BFCOLOR.GRAY110}>
{bItem.bName}
</BFText>
</TouchableOpacity>
</View>
))}
JavaScript
복사
Draggable Flatlist에 적용 시 문제점
1.
flatlist에서 사용됐던 onScroll을 사용할 수 없음. 해당 부분은 onScrollOffsetChange로 대체해서 사용함.
2.
onScrollOffsetChange를 사용할 경우, onScroll과 동일하게 현재 스크롤의 위치(offset)를 받을 수 있음.
3.
다만 여기서 문제는 카테고리 변경 시 저장된 스크롤의 위치를 적용할 때, 적용된 스크롤의 값이 실제 저장된 값과 상이함.
Draggable Flatlist 구현 코드
•
ExerciseManageScreen.tsx (운동 리스트 수정)
const categoryRef = useRef(filteredResult.bId);
const listRef = useRef(null);
const scrollPositions = useRef({}); // 각 카테고리별 스크롤 위치 저장용
categoryRef.current = filteredResult.bId;
const isScrolled = useRef(SCROLL_DEFAULT);
const handleScrollOffsetChange = (offset) => {
if (isScrolled.current !== SCROLL_PROCESS) {
scrollPositions.current[categoryRef.current] = offset;
console.log('스크롤 offset 갱신', offset);
} else {
console.log('isScrolled 불가능 상태');
isScrolled.current = SCROLL_CHANGED;
}
};
// 카테고리 변경 시 해당 카테고리에 맞는 스크롤 위치 적용
const handleBodyPartChange = (bId) => {
console.log('카테고리 변경', bId);
const y = scrollPositions.current[bId] || 0;
console.log('저장된 스크롤 값', scrollPositions.current[bId]);
listRef.current.scrollToOffset({ offset: y, animated: false });
console.log('저장된 스크롤 값 적용');
isScrolled.current = SCROLL_PROCESS;
console.log('isScrolled 값 변경');
};
JavaScript
복사
•
handleBodyPartChange 함수를 호출할 때 y값은 이전에 저장된 스크롤 위치의 값이 나온다.
•
다만 스크롤이 이동하는 중에 handleScrollOffsetChange 함수가 호출되고, 이때 받게되는 offset값은 저장된 스크롤 위치값과 다르다.
•
handleScrollOffsetChange 함수가 호출되며 저장된 스크롤 값이 갱신되는 것이 문제인가 싶어서 isScrolled 라는 ref값을 추가했지만, listRef.current.scrollToOffset({ offset: y, animated: false }); 이 명확하게 먼저 호출됐음에도 지속적으로 스크롤 위치가 맞지 않는 문제가 생김.
•
해당 코드 실행 시 console 내역
LOG 스크롤 offset 갱신 1760 // handleScrollOffsetChange 함수
LOG 카테고리 변경 2 // 가슴 카테고리로 변경
LOG 저장된 스크롤 값 undefined // 해당 카테고리는 아직 저장된 스크롤 위치가 없어서 0으로 적용
LOG 저장된 스크롤 값 적용
LOG isScrolled 값 변경
LOG isScrolled 불가능 상태
LOG 카테고리 변경 1 // 다시 하체 카테고리로 변경
LOG 저장된 스크롤 값 1760 // 저장된 스크롤 위치 확인
LOG 저장된 스크롤 값 적용 // listRef.current.scrollToOffset 호출 후 로그 찍음
LOG isScrolled 값 변경 // isScrolled의 값을 SCROLL_PROGRESS로 변경해서 handleScrollOffsetChange가 스크롤 위치 갱신 못 하게 막음
LOG isScrolled 불가능 상태 // handleScrollOffsetChange 함수 호출됐지만 갱신 불가능 -> 가능 상태로 변경
LOG 스크롤 offset 갱신 1328 // listRef.current.scrollToOffset로 적용한 스크롤 값과 다른 지점에서 스크롤이 멈춤
JavaScript
복사
◦
해당 이슈에 대한 원인은대한 원인은 찾지 못 한 상태