ScrollView vs FlatList
친구목록을 만들때 사용했던 ScrollView는 데이터가 단순히 화면을 벗어났을때 스크롤을 생성해서
스와이프를 통해 벗어난 부분을 보여줄수있게하는데 목적이 있다.
따라서 데이터 양이 많지 않고 고정적일때 보통 사용한다.
=> 친구목록을 구현할때 적절하지않음.
flatList로 바꿔보겠다.
한번에 모든 데이터 대신,
화면에 보여지는 부분만 렌더링 하기 때문에 ScrollView에 비해 압도적인 성능을 보여줌!
FlatList로 수정하기
index.tsx
FriendList컴포넌트에서 map안에서 돌리던 부분을 FlatList renderItem에 전달
import { friendProfiles, myProfile } from "@/assets/data";
import Division from "@/components/Division";
import FriendSection from "@/components/FriendSection";
import Header from "@/components/Header";
import Margin from "@/components/Margin";
import Profile from "@/components/Profile";
import { useState } from "react";
import { FlatList, View } from "react-native";
export default function HomeScreen() {
const [isFriendSectionOpen, setIsFriendSectionOpen] = useState(true);
const ListHeaderComponent = () => (
<View style={{ backgroundColor: "#fff" }}>
<Header />
{/* 컴포넌트별 간격 지정시 명시적으로 height주는게 좋음 */}
<Margin height={6} />
<Profile
source={myProfile.source}
name={myProfile.name}
introduction={myProfile.introduction}
/>
<Margin height={10} />
<Division />
<Margin height={10} />
<FriendSection
friendProfileLen={friendProfiles.length}
onPress={() => setIsFriendSectionOpen(!isFriendSectionOpen)}
isOpen={isFriendSectionOpen}
/>
<Margin height={5} />
</View>
);
const ListFooterComponent = () => <Margin height={10} />;
const ItemSeparatorComponent = () => <Margin height={10} />;
const renderItem = ({ item }: any) => (
<View>
<Profile
name={item.name}
source={item.source}
introduction={item.introduction}
size={"small"}
/>
</View>
);
return (
<View style={{ paddingHorizontal: 20 }}>
<FlatList
data={isFriendSectionOpen ? friendProfiles : []} // 상태에 따라 데이터 동적변경
keyExtractor={(_, index) => index.toString()} // 키 속성
ItemSeparatorComponent={ItemSeparatorComponent} // 마진 컴포넌트
renderItem={renderItem} // 리스트안에 렌더할 아이템
ListHeaderComponent={ListHeaderComponent} // 리스트상단 컴포넌트
ListFooterComponent={ListFooterComponent} // 리스트하단 컴포넌트
stickyHeaderIndices={[0]} // ListHeaderComponent를 고정시키는 속성
showsVerticalScrollIndicator={false} // 스크롤바 안보이게
></FlatList>
</View>
);
}
renderItem안쪽 View에 key를 FlatList에 keyExtractor로 넣을 수 있음keyExtractor={(_, index) => index.toString()}
string으로 반환해야돼서 index는 number라 toString필요
(키값을 index로 쓰는건 당연히 비추천. 데이터에 고유한 id값을 넣고 그걸 key로 사용해야함)
프로필사이에 간격을 주기 위해 마진컴포넌트를 넣었었는데
이것도 renderItem에 넣지 않고 따로 뺄 수 있음
FlatList의 위에 위치하는 헤더컴포넌트를 ListHeaderComponent에 넣을 수 있고,
헤더를 고정할수있는데 stickyHeaderIndices에 인덱스번호로 지정가능하다.
친구목록 토글은 data에서 data={isFriendSectionOpen ? friendProfiles : []}
false일때 빈배열보내는 방법으로 구현 가능
스크롤바 보이지 않게 설정하는것은 showsVerticalScrollIndicator를 false로 보내주면됨.
마진 정리
FriendSection하단에 Margin 5,
FlatList에 ListFooterComponent로 Margin 10을 추가함
코드 리팩토링
Profile
import { ProfileType } from "@/assets/data";
import React from "react";
import { Image, Text, View } from "react-native";
interface MyProfileProps extends ProfileType {
isMe: boolean;
}
export default ({ isMe, source, name, introduction }: MyProfileProps) => {
const size = isMe ? 50 : 40;
return (
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Image source={source} style={{ width: size, height: size, borderRadius: size * 0.4 }} />
<View style={{ justifyContent: "center", marginLeft: 12 }}>
<Text style={{fontWeight: isMe ? 700 : 500, fontSize: isMe ? 16 : 15,}}>{name}</Text>
{!!introduction && ( // introduction이 존재할 때만 렌더링(falsy값이면 렌더링 안함)
<View>
<View style={{ height: isMe ? 6 : 2 }} />
<Text style={{ fontSize: isMe ? 12 : 11, color: "gray" }}>{introduction}</Text>
</View>
)}
</View>
</View>
);
};
사이즈를 large or small로 받기보다
내 프로필이냐, 아니냐 두 경우밖에 없으므로 isMe boolean으로 받고
프로필 컴포넌트 내에서 size를 true / false 일때 각각 지정하여 사용
이미지를 한번 감싸는 view 등 불필요한 요소와 스타일 삭제
좀 더 간결해졌다.
TabButton
<TouchableOpacity
activeOpacity={1}
onPress={onPress}
style={{ paddingBottom: insets.bottom, flex: 1, alignItems: "center" , justifyContent: "center"}}
>
TabButton컴포넌트의 TouchableOpacity에 클릭시 투명도 변화는 불필요하여 activeOpacity={1}
추가
'Frontend > React Native' 카테고리의 다른 글
React Native 2-1. 카카오톡 친구목록 클론코딩(5): 친구목록 컴포넌트 (1) | 2025.03.15 |
---|---|
React Native 2-1. 카카오톡 친구목록 클론코딩(4): 친구목록 상단 컴포넌트들 (0) | 2025.03.15 |
React Native 2-1. 카카오톡 친구목록 클론코딩(3): expo 기본앱에서 tabbar 커스텀 하기 (0) | 2025.03.13 |
React Native 2-1. 카카오톡 친구목록 클론코딩(2) (0) | 2025.03.10 |
React Native 2-1. 카카오톡 친구목록 클론코딩(1) (0) | 2025.03.10 |