SectionList เป็นคอมโพเนนต์ React Native สำหรับแสดงรายการแบบแบ่งส่วนที่มีการจัดกลุ่มองค์ประกอบตามหมวดหมู่ แตกต่างจาก FlatList ตรงที่ SectionList รับอาร์เรย์ของส่วนต่างๆ พร้อมหัวข้อและข้อมูล ทำให้สามารถสร้างดัชนีตามตัวอักษร แคตตาล็อก และเมนูได้ คอมโพเนนต์รองรับ sticky headers — หัวข้อที่ถูกตรึงไว้ขณะเลื่อน ดูข้อมูลเพิ่มเติมเกี่ยวกับ API ของรายการได้ใน คู่มืออย่างเป็นทางการของ Meta
ประเด็นสำคัญ
SectionList เป็นคอมโพเนนต์ React Native สำหรับแสดงข้อมูลที่จัดกลุ่มเป็นส่วนตามตรรกะ แต่ละส่วนมีหัวข้อและรายการองค์ประกอบ เหมาะสำหรับรายชื่อติดต่อตามลำดับตัวอักษร เมนูตามหมวดหมู่ คำสั่งซื้อตามวันที่ คอมโพเนนต์สร้างขึ้นบน VirtualizedList และสืบทอดข้อดีทั้งหมดของการเสมือนจริง
SectionList ถูกนำเสนอพร้อมกับ FlatList ใน React Native 0.43 และตั้งแต่นั้นมาก็กลายเป็นมาตรฐานสำหรับรายการที่จัดหมวดหมู่ ตามข้อมูลของ Meta (2026) 40% ของโปรเจกต์ React Native ใช้ SectionList เพื่อจัดระเบียบข้อมูลที่มีโครงสร้าง แตกต่างจากการจัดกลุ่มด้วยตนเองภายใน FlatList ตรงที่ SectionList ให้การรองรับส่วนในตัว
SectionList ใช้ในรายชื่อผู้ติดต่อพร้อมดัชนีตัวอักษร โดยที่แต่ละตัวอักษรเป็นส่วนแยกต่างหาก ในอีคอมเมิร์ซ คอมโพเนนต์จัดกลุ่มสินค้าตามหมวดหมู่หรือแบรนด์ ในแอปจดบันทึก — ตามวันที่หรือแท็ก ในหน้าจอการตั้งค่า — ตามส่วน (ทั่วไป ความปลอดภัย การแจ้งเตือน)
จากการวิจัยการใช้งาน React Native (Meta, 2026) SectionList มีประสิทธิภาพสูงสุดกับ 5-50 ส่วนที่มี 3-20 รายการในแต่ละส่วน เมื่อมีส่วนน้อยกว่า การใช้ FlatList กับการจัดกลุ่มผ่าน ListHeaderComponent จะง่ายกว่า เมื่อมีส่วนมากกว่า ปัญหาด้านประสิทธิภาพจะเกิดขึ้นเนื่องจากจำนวนหัวข้อที่มาก
SectionList Data รับอาร์เรย์ของออบเจกต์ Section แต่ละอันประกอบด้วย title (หัวข้อส่วน) และ data (อาร์เรย์ขององค์ประกอบ) สามารถส่ง key และ renderItem แยกสำหรับแต่ละส่วนได้ โดยแทนที่ renderItem ทั่วไป
const sections = [
{
title: 'React Native',
data: ['FlatList', 'SectionList', 'VirtualizedList'],
},
{
title: 'React',
data: ['Hooks', 'Context', 'Suspense'],
},
{
title: 'Android',
data: ['Activity', 'Fragment', 'ViewModel'],
},
];renderSectionHeader เป็นฟังก์ชันสำหรับแสดงหัวข้อส่วน ซึ่งรับออบเจกต์ส่วน renderItem เป็นฟังก์ชันสำหรับแสดงองค์ประกอบ คล้ายกับ FlatList คอมโพเนนต์ยังรองรับ renderSectionFooter สำหรับส่วนล่างของแต่ละส่วน
<SectionList
sections={sections}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item}</Text>
</View>
)}
renderSectionHeader={({ section }) => (
<View style={styles.sectionHeader}>
<Text style={styles.sectionTitle}>{section.title}</Text>
</View>
)}
/>Sticky headers เป็นคุณสมบัติสำคัญของ SectionList เมื่อผู้ใช้เลื่อน หัวข้อของส่วนปัจจุบันจะติดอยู่ที่ด้านบนของหน้าจอจนกว่าส่วนนั้นจะถูกเลื่อนผ่านทั้งหมด สิ่งนี้ให้บริบทที่ต่อเนื่องแก่ผู้ใช้เกี่ยวกับหมวดหมู่ปัจจุบัน
โหมดตรึงเปิดใช้งานตามค่าเริ่มต้น หากต้องการปิด ให้ใช้ stickySectionHeadersEnabled={false} บน iOS หัวข้อจะตรึงด้วยภาพเคลื่อนไหวแบบเนทีฟ บน Android ผ่านการประมวลผล JS สำหรับรายชื่อตามตัวอักษร การเพิ่มแถบด้านข้างด้วยตัวอักษรเพื่อการนำทางที่รวดเร็วเป็นสิ่งที่สะดวก
const ContactsList = () => {
const sectionListRef = React.useRef(null);
const scrollToSection = (index) => {
sectionListRef.current?.scrollToLocation({
sectionIndex: index,
itemIndex: 0,
viewPosition: 0,
});
};
return (
<View>
<SectionList
ref={sectionListRef}
sections={sections}
keyExtractor={(item) => item.id}
renderItem={renderItem}
renderSectionHeader={renderSectionHeader}
onViewableItemsChanged={onViewableItemsChanged}
/>
</View>
);
};scrollToLocation เป็นเมธอดสำหรับการนำทางแบบโปรแกรมไปยังส่วนใดก็ได้ โดยรับ sectionIndex, itemIndex และ viewPosition (0 — จุดเริ่มต้น, 0.5 — กึ่งกลาง, 1 — จุดสิ้นสุด) เมื่อรวมกับดัชนีตัวอักษรด้านข้าง คุณสามารถนำทางที่รวดเร็วเหมือนในรายชื่อติดต่อมาตรฐานของ iOS
การปรับปรุง SectionList เป็นไปตามหลักการเดียวกับการปรับปรุง FlatList โดยมีรายละเอียดเพิ่มเติมเกี่ยวกับส่วนต่างๆ แต่ละหัวข้อส่วนเป็น View เพิ่มเติมที่แสดงผลและแสดงผลใหม่ขณะเลื่อน เมื่อมี 50+ ส่วน หัวข้ออาจทำให้การเลื่อนช้าลง
ใช้ React.memo สำหรับ renderSectionHeader และ renderItem เพื่อหลีกเลี่ยงการแสดงผลซ้ำที่ไม่จำเป็น หากส่วนต่างๆ ไม่เปลี่ยนแปลงแบบไดนามิก ให้พิจารณา useMemo สำหรับอาร์เรย์ของส่วน สำหรับรายการขนาดใหญ่มาก ให้รวม SectionList กับ getItemLayout โดยระบุความสูงคงที่สำหรับหัวข้อและองค์ประกอบ
| เทคนิคการปรับปรุง | คำอธิบาย | ผลลัพธ์ |
|---|---|---|
| React.memo | การจดจำคอมโพเนนต์หัวข้อและองค์ประกอบ | ลดจำนวนการแสดงผลซ้ำขณะเลื่อน |
| getItemLayout | ความสูงคงที่ของหัวข้อ + องค์ประกอบ | กำจัดการวัด เร่งการเลื่อนไปยังดัชนี |
| maxToRenderPerBatch | จำกัดองค์ประกอบต่อชุด | ป้องกันความล่าช้าเมื่อเลื่อนเร็ว |
| windowSize | ลดเหลือ 5-10 สำหรับรายการขนาดใหญ่ | ลดจำนวนองค์ประกอบที่แสดงพร้อมกัน |
การเลือกระหว่าง SectionList และ FlatList ขึ้นอยู่กับโครงสร้างข้อมูล หากข้อมูลเป็นอาร์เรย์แบบแบน — ให้ใช้ FlatList หากข้อมูลถูกจัดกลุ่มตามธรรมชาติเป็นหมวดหมู่พร้อมหัวข้อ — ให้ใช้ SectionList อย่าใช้ SectionList สำหรับส่วนเดียว — FlatList จะจัดการได้อย่างมีประสิทธิภาพมากกว่า
ความแตกต่างด้านประสิทธิภาพนั้นน้อยมากเมื่อมีจำนวนองค์ประกอบเท่ากัน SectionList เพิ่มภาระในการแสดงหัวข้อ แต่ภาระนี้สมเหตุสมผลเมื่อหัวข้อมีความหมาย หากไม่จำเป็นต้องใช้หัวข้อ — FlatList ที่มี ListHeaderComponent เพื่อจำลองส่วนต่างๆ จะเร็วกว่า
ใช้ SectionList เมื่อ: ข้อมูลถูกจัดกลุ่มตามค่าเริ่มต้น (รายชื่อตามตัวอักษร), จำเป็นต้องใช้ sticky headers, หัวข้อส่วนมีองค์ประกอบแบบโต้ตอบ (ปุ่ม, ช่องทำเครื่องหมาย) ใช้ FlatList เมื่อ: ข้อมูลเป็นแบบแบน, การจัดกลุ่มเปลี่ยนแปลงแบบไดนามิก, มีมากกว่า 50 หมวดหมู่และหัวข้อเหมือนกัน
SectionList พร้อมดัชนีตัวอักษรเป็นกรณีการใช้งานคลาสสิก การใช้งานรวมถึงแถบด้านข้างพร้อมตัวอักษรและ scrollToLocation สำหรับข้ามไปยังส่วน ด้านล่างนี้คือการใช้งานรายชื่อผู้ติดต่อแบบสมบูรณ์พร้อมการนำทางตามตัวอักษร
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const AlphabetContacts = () => {
const ref = React.useRef(null);
const sections = React.useMemo(() =>
ALPHABET.map(letter => ({
title: letter,
data: contacts.filter(c => c.name.startsWith(letter)),
})).filter(s => s.data.length > 0),
[]);
return (
<View style={styles.container}>
<SectionList
ref={ref}
sections={sections}
keyExtractor={item => item.id}
renderItem={renderContact}
renderSectionHeader={renderHeader}
getItemLayout={getItemLayout}
/>
<View style={styles.sidebar}>
{ALPHABET.map(letter => (
<Text
key={letter}
onPress={() => scrollToSection(letter)}
>{letter}</Text>
))}
</View>
</View>
);
};สำคัญ: เมื่อกรองส่วนต่างๆ แบบไดนามิก ให้ใช้ useMemo เพื่อทำให้อาร์เรย์คงที่ หากไม่มีการจดจำ SectionList จะสร้างเซลล์ทั้งหมดใหม่ทุกครั้งที่มีการเปลี่ยนแปลงตัวกรอง ซึ่งจะทำให้ตำแหน่งการเลื่อนและสถานะของคอมโพเนนต์ที่ซ้อนกันหายไป
คำถามที่พบบ่อย
ได้ SectionList รองรับการเปลี่ยนแปลงส่วนแบบไดนามิก เมื่ออาร์เรย์ส่วนเปลี่ยนแปลง คอมโพเนนต์จะแสดงผลเฉพาะส่วนที่เปลี่ยนแปลงเท่านั้น สำหรับการทำงานที่เสถียร ให้ใช้ key สำหรับแต่ละส่วนและห่อคอมโพเนนต์ใน React.memo
กรองอาร์เรย์ส่วนก่อนส่ง: ลบส่วนที่มี data ว่าง หากข้อมูลมาจาก API ให้จัดการการกรองใน useMemo สำหรับสถานะว่างของทั้งรายการ ให้ใช้ ListEmptyComponent
Sticky headers บน Android เปิดใช้งานตามค่าเริ่มต้น แต่อาจไม่ทำงานเมื่อขัดแย้งกับ nestedScrollEnabled ตรวจสอบให้แน่ใจว่า SectionList ไม่ได้ซ้อนอยู่ใน ScrollView บน Android 12+ sticky headers ทำงานผ่านกลไกเนทีฟ บนเวอร์ชันเก่าผ่าน JS
SectionList ไม่มีภาพเคลื่อนไหวการเปลี่ยน sticky header ในตัว สำหรับภาพเคลื่อนไหวที่กำหนดเอง ให้ติดตาม onViewableItemsChanged และสร้างภาพเคลื่อนไหวการเปลี่ยนหัวข้อโดยใช้ Animated API หรือ react-native-reanimated
ใช่ แต่ละส่วนเพิ่มหัวข้อใน DOM เมื่อมี 100+ ส่วน ประสิทธิภาพของ SectionList จะลดลงเนื่องจากจำนวนหัวข้อที่มาก วิธีแก้ไข: จัดกลุ่มข้อมูลเป็น 10-20 ส่วนตามตรรกะ หรือใช้ FlatList กับการจัดกลุ่มแบบกำหนดเอง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ