การสร้างแอปรายการรายชื่อติดต่อ
ผสาน SectionList ส่วนหัวตามตัวอักษร ตัวกรองค้นหา และการดึงเพื่อรีเฟรช เพื่อสร้างหน้ารายชื่อติดต่อที่สมจริงและเลื่อนได้อย่างลื่นไหล
การสร้างแอปรายการรายชื่อติดต่อ เป็นบทเรียน React Native Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Native Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
App Overview: Contacts List
In this lesson you will build a realistic contacts list screen that combines everything from the FlatList and SectionList lessons. The app will display contacts grouped alphabetically, support a search filter, allow pull-to-refresh, and maintain smooth performance even with hundreds of entries.
Defining the Contacts Data
Start with a static array of contact objects. In a real app this would come from the device's contacts API or a remote server. Each contact has an id, name, and phone. A unique numeric or string ID is essential for the keyExtractor.
const CONTACTS = [
{ id: '1', name: 'Alice Brown', phone: '+1-555-0101' },
{ id: '2', name: 'Andrew Chen', phone: '+1-555-0102' },
{ id: '3', name: 'Bob Davis', phone: '+1-555-0201' },
{ id: '4', name: 'Carol Evans', phone: '+1-555-0301' },
// ... more contacts
];Search Filter State
Add a searchQuery state variable and filter the contacts array before grouping. The filter converts both the query and contact name to lowercase for a case-insensitive match. Wrap the filtering and grouping in useMemo so it only recomputes when the contacts or query changes.
const [searchQuery, setSearchQuery] = useState('');
const filteredContacts = useMemo(() => {
if (!searchQuery) return CONTACTS;
return CONTACTS.filter((c) =>
c.name.toLowerCase().includes(searchQuery.toLowerCase())
);
}, [searchQuery]);Grouping Contacts Alphabetically
Convert the filtered flat array into the SectionList sections format. Reduce the contacts into a map keyed by the first letter, then sort the keys and map them to section objects. This transformation runs inside useMemo alongside the filter for a single computed value.
const sections = useMemo(() => {
const map = filteredContacts.reduce((acc, contact) => {
const letter = contact.name[0].toUpperCase();
if (!acc[letter]) acc[letter] = [];
acc[letter].push(contact);
return acc;
}, {});
return Object.keys(map).sort().map((key) => ({
title: key,
data: map[key],
}));
}, [filteredContacts]);Search Bar Component
Render a TextInput above the SectionList as the ListHeaderComponent so it scrolls with the list. Bind it to searchQuery state with onChangeText. Use the clearButtonMode prop on iOS to show a native clear button inside the input.
const SearchBar = () => (
<TextInput
style={styles.searchBar}
placeholder='Search contacts...'
value={searchQuery}
onChangeText={setSearchQuery}
clearButtonMode='while-editing'
/>
);Contact Row Component
Build a memoized row component using React.memo to prevent unnecessary re-renders. The row shows the contact's initials in a colored avatar circle and their name and phone number on the right. Memoizing the row component is critical for smooth scrolling with hundreds of contacts.
const ContactRow = React.memo(({ item }) => (
<View style={styles.row}>
<View style={styles.avatar}>
<Text style={styles.initials}>{item.name[0]}</Text>
</View>
<View>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.phone}>{item.phone}</Text>
</View>
</View>
));Section Header Component
The alphabetic section header is a simple View with the letter. Give it a distinct background color and sticky behavior so it stays visible as the user scrolls through each letter group. Keep the component small and memoized since it renders once per letter.
const SectionHeader = ({ section }) => (
<View style={styles.sectionHeader}>
<Text style={styles.sectionTitle}>{section.title}</Text>
</View>
);Pull-to-Refresh Integration
Simulate refreshing by introducing a refreshing state. On refresh, clear the search query (so users see all contacts again), wait briefly to simulate a network call, then set refreshing to false. In a real app you would re-fetch from the device contacts API or the server.
const [refreshing, setRefreshing] = useState(false);
const onRefresh = () => {
setRefreshing(true);
setSearchQuery('');
setTimeout(() => setRefreshing(false), 1000);
};Empty State When No Results
When the filtered sections array is empty (no contacts match the search), display an informative empty state using ListEmptyComponent. Tell the user no contacts match their query and suggest they clear the search. This is far better than showing a blank screen.
const ListEmpty = () => (
<View style={styles.empty}>
<Text>No contacts found for '{searchQuery}'</Text>
<Button title='Clear Search' onPress={() => setSearchQuery('')} />
</View>
);Assembling the Full Screen
Combine all the pieces: SectionList with the sections data, memoized renderItem, renderSectionHeader, keyExtractor, sticky headers, pull-to-refresh, and ListHeaderComponent for the search bar. The result is a production-quality contacts screen.
export default function ContactsScreen() {
return (
<SectionList
sections={sections}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <ContactRow item={item} />}
renderSectionHeader={({ section }) => <SectionHeader section={section} />}
stickySectionHeadersEnabled
refreshing={refreshing}
onRefresh={onRefresh}
ListHeaderComponent={SearchBar}
ListEmptyComponent={ListEmpty}
/>
);
}Navigating to a Contact Detail Screen
Make each row tappable by wrapping the ContactRow in a TouchableOpacity that calls navigation.navigate('ContactDetail', { contactId: item.id }). The detail screen reads the ID from route.params and fetches the full contact data, following the React Navigation pattern you learned earlier.
const ContactRow = React.memo(({ item, onPress }) => (
<TouchableOpacity onPress={() => onPress(item)} style={styles.row}>
<View style={styles.avatar}>
<Text style={styles.initials}>{item.name[0]}</Text>
</View>
<View>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.phone}>{item.phone}</Text>
</View>
</TouchableOpacity>
));Quick Check
Test your understanding of the Contacts List App architecture from this lesson.
Lesson Recap
In this lesson you learned: combine SectionList, search filtering, and useMemo for an efficient contacts screen, memoize row components with React.memo to maintain scroll performance, and integrate pull-to-refresh and empty states for a polished UX. Next up we dive into the useRef hook and mutable values.
เรียนรู้ JavaScript ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การสร้างแอปรายการรายชื่อติดต่อ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างแอปรายการรายชื่อติดต่อ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Native Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างแอปรายการรายชื่อติดต่อ”
ผสาน SectionList ส่วนหัวตามตัวอักษร ตัวกรองค้นหา และการดึงเพื่อรีเฟรช เพื่อสร้างหน้ารายชื่อติดต่อที่สมจริงและเลื่อนได้อย่างลื่นไหล คุณปฏิบัติ React Native Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Native Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Native Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างแอปรายการรายชื่อติดต่อ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน React Native Academy นี้ได้ไหม
ได้ บทเรียน React Native Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ข้อมูล FlatList, renderItem และ keyExtractor
- การดึงเพื่อรีเฟรชและโหลดเพิ่มเติม
- SectionList พร้อมส่วนหัว
- การสร้างแอปรายการรายชื่อติดต่อ