SectionList es un componente de React Native para mostrar listas seccionadas con elementos agrupados por categorías. A diferencia de FlatList, SectionList acepta un array de secciones con encabezados y datos, lo que permite crear índices alfabéticos, catálogos y menús. El componente admite sticky headers — encabezados fijos al hacer scroll. Más información sobre las API de listas en la guía oficial de Meta.
Puntos clave
SectionList es un componente de React Native para mostrar datos agrupados en secciones lógicas. Cada sección tiene un encabezado y una lista de elementos, ideal para contactos por orden alfabético, menús por categorías, pedidos por fecha. El componente está construido sobre VirtualizedList y hereda todas las ventajas de la virtualización.
SectionList apareció junto con FlatList en React Native 0.43 y desde entonces es el estándar para listas categorizadas. Según Meta (2026), el 40% de los proyectos en React Native utilizan SectionList para organizar datos estructurados. A diferencia del agrupamiento manual dentro de FlatList, SectionList proporciona soporte integrado para secciones.
SectionList se utiliza en listas de contactos con índice alfabético, donde cada letra es una sección independiente. En comercio electrónico, el componente agrupa productos por categoría o marca. En aplicaciones de notas — por fecha o etiquetas. En pantallas de configuración — por secciones (General, Seguridad, Notificaciones).
Según un estudio de uso de React Native (Meta, 2026), SectionList es más eficaz con 5-50 secciones de 3-20 elementos cada una. Con menos secciones, es más sencillo usar FlatList con agrupamiento mediante ListHeaderComponent. Con más secciones, surgen problemas de rendimiento debido al gran número de encabezados.
SectionList Data acepta un array de objetos Section, cada uno contiene title (encabezado de sección) y data (array de elementos). Opcionalmente, se puede pasar key y renderItem para cada sección por separado, sobrescribiendo el renderItem común.
const sections = [
{
title: 'React Native',
data: ['FlatList', 'SectionList', 'VirtualizedList'],
},
{
title: 'React',
data: ['Hooks', 'Context', 'Suspense'],
},
{
title: 'Android',
data: ['Activity', 'Fragment', 'ViewModel'],
},
];renderSectionHeader es una función para renderizar el encabezado de sección, que recibe el objeto de sección. renderItem es la función de renderizado de elementos, similar a FlatList. El componente también admite renderSectionFooter para la parte inferior de cada sección.
<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 son una característica clave de SectionList. Cuando el usuario se desplaza, el encabezado de la sección actual se fija en la parte superior de la pantalla hasta que la sección se haya desplazado completamente. Esto proporciona al usuario un contexto constante sobre la categoría actual.
El modo sticky está activado por defecto. Para desactivarlo, use stickySectionHeadersEnabled={false}. En iOS, los encabezados se fijan con animación nativa; en Android, mediante procesamiento JS. Para directorios alfabéticos, es conveniente añadir un panel lateral con letras para navegación rápida.
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 es un método para navegación programática a cualquier sección. Acepta sectionIndex, itemIndex y viewPosition (0 — inicio, 0.5 — centro, 1 — final). Combinado con un índice alfabético lateral, se puede implementar una navegación rápida como en los contactos estándar de iOS.
La optimización de SectionList sigue los mismos principios que la optimización de FlatList, con matices adicionales relacionados con las secciones. Cada encabezado de sección es una View adicional que se renderiza y se vuelve a renderizar durante el desplazamiento. Con 50+ secciones, los encabezados pueden ralentizar el scroll.
Use React.memo para renderSectionHeader y renderItem para evitar renderizados innecesarios. Si las secciones no cambian dinámicamente, considere useMemo para el array de secciones. Para listas muy grandes, combine SectionList con getItemLayout, especificando alturas fijas para encabezados y elementos.
| Técnica de optimización | Descripción | Efecto |
|---|---|---|
| React.memo | Memorización de componentes de encabezados y elementos | Reduce la cantidad de renderizados durante el scroll |
| getItemLayout | Altura fija de encabezado + elemento | Elimina la medición, acelera el scroll hasta el índice |
| maxToRenderPerBatch | Limitar elementos por lote | Evita retrasos durante el scroll rápido |
| windowSize | Reducir a 5-10 para listas grandes | Reduce la cantidad de elementos renderizados simultáneamente |
La elección entre SectionList y FlatList depende de la estructura de datos. Si los datos son un array plano — use FlatList. Si los datos se agrupan naturalmente en categorías con encabezados — use SectionList. No use SectionList para una sola sección — FlatList lo manejará de manera más eficiente.
La diferencia de rendimiento es mínima con la misma cantidad de elementos. SectionList añade sobrecarga al renderizar encabezados, pero esta sobrecarga está justificada cuando los encabezados tienen carga semántica. Si no se necesitan encabezados — FlatList con ListHeaderComponent para simular secciones será más rápido.
Use SectionList cuando: los datos están agrupados por defecto (contactos por letra), se necesitan sticky headers, los encabezados de sección contienen elementos interactivos (botones, casillas). Use FlatList cuando: los datos son planos, la agrupación cambia dinámicamente, hay más de 50 categorías y los encabezados son uniformes.
SectionList con índice alfabético es un caso de uso clásico. La implementación incluye un panel lateral con letras y scrollToLocation para saltar a una sección. A continuación, una implementación completa de una lista de contactos con navegación alfabética.
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>
);
};Importante: al filtrar dinámicamente las secciones, use useMemo para estabilizar el array. Sin memorización, SectionList recreará todas las celdas en cada cambio de filtro, lo que provocará pérdida de la posición de scroll y el estado de los componentes anidados.
Preguntas frecuentes
Sí, SectionList admite cambios dinámicos de secciones. Al cambiar el array de secciones, el componente solo vuelve a renderizar las secciones modificadas. Para un funcionamiento estable, use una key para cada sección y envuelva los componentes en React.memo.
Filtre el array de secciones antes de pasarlo: elimine las secciones con data vacío. Si los datos provienen de una API, maneje el filtrado en useMemo. Para el estado vacío de toda la lista, use ListEmptyComponent.
Sticky headers en Android están activados por defecto, pero pueden no funcionar si hay conflicto con nestedScrollEnabled. Asegúrese de que SectionList no esté anidado dentro de un ScrollView. En Android 12+, los sticky headers funcionan mediante el mecanismo nativo; en versiones anteriores, mediante JS.
SectionList no proporciona una animación de transición integrada para sticky headers. Para una animación personalizada, monitoree onViewableItemsChanged y anime el cambio de encabezado usando Animated API o react-native-reanimated.
Sí, cada sección añade un encabezado al DOM. Con 100+ secciones, el rendimiento de SectionList disminuye debido a la gran cantidad de encabezados. Solución: agrupe los datos en 10-20 secciones lógicas o use FlatList con agrupamiento personalizado.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también