Scroll infinito no React Native
Em muitos casos precisamos tomar cuidado com o carregamento de muitos componentes em listas no React Native. No exemplo desse post iremos utilizar a API de busca de repositórios do Github que nos permite paginar sobre os resultados.
Exemplo de chamada à API buscando pela palavra react
com 20 itens por página e na página 5: https://api.github.com/search/repositories?q=react&page=5&per_page=20
Bora ver como isso fica na prática!
Configurando FlatList
Primeiramente vamos configurar nosso componente para renderizar uma FlatList com alguns dados de exemplo armazenados no estado:
import React, { Component } from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
export default class App extends Component {
state = {
data: [
{ id: 0, full_name: 'Repo 1' },
{ id: 1, full_name: 'Repo 2' },
{ id: 2, full_name: 'Repo 3' },
{ id: 3, full_name: 'Repo 4' },
{ id: 4, full_name: 'Repo 5' },
],
};
renderItem = ({ item }) => (
<View style={styles.listItem}>
<Text>{item.full_name}</Text>
</View>
);
render() {
return (
<FlatList
style={{ marginTop: 30 }}
contentContainerStyle={styles.list}
data={this.state.data}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
);
}
}
const styles = StyleSheet.create({
list: {
paddingHorizontal: 20,
},
listItem: {
backgroundColor: '#EEE',
marginTop: 20,
padding: 30,
},
});
O resultado do código deve ser assim:
Agora com a interface pré-configurada vamos buscar os dados da API do Github para preencher a lista com os primeiros 20 itens.
Vou começar definindo 3 variáveis acima de nossa classe apenas para centralizar as informações importantes:
const baseURL = 'https://api.github.com';
const searchTerm = 'react';
const perPage = 20;
Agora, vamos criar uma função chamada loadRepositories
e invocá-la no método componentDidMount
para preencher nosso estado, além disso, alterei meu estado para armazenar o valor da página atual e da informação de carregamento de novos resultados:
export default class App extends Component {
state = {
data: [],
page: 1,
loading: false,
};
componentDidMount() {
this.loadRepositories();
}
loadRepositories = async () => {
if (this.state.loading) return;
const { page } = this.state;
this.setState({ loading: true });
const response = await fetch(`${baseURL}/search/repositories?q=${searchTerm}&per_page=${perPage}&page=${page}`);
const repositories = await response.json();
this.setState({
data: [ ...this.state.data, ...repositories.items ],
page: page + 1,
loading: false,
});
}
// Resto da classe
}
O método loadRepositories
é utilizado para o carregamento inicial da nossa lista, mas devido à linha 23 que realiza a concatenação dos valores recebidos da API ao estado e à linha 24 que aumenta o número da página atual, podemos utilizar esse método também para carregamento dos novos itens quando chegamos ao fim da lista.
Até agora sua aplicação deve estar assim:
Vamos adicionar agora os métodos que darão funcionamento ao scroll infinito na nossa FlatList:
<FlatList
...
onEndReached={this.loadRepositories}
onEndReachedThreshold={0.1}
/>
A propriedade onEndReachedThreshold
define basicamente o percentual de distância do fim que o usuário deve chegar para carregar novos dados, nesse caso, 0.1 significa 10%.
Se tudo ocorreu bem até agora, sua aplicação deve estar tendo esse comportamento:
Legal, nosso scroll infinito já está funcionando, apenas para melhorar a interface vamos adicionar um loading no fim da lista sempre que estivermos realizando o carregamento de novos itens:
<FlatList
...
ListFooterComponent={this.renderFooter}
/>
E podemos importar o componente ActivityIndicator
do React Native e criar um método renderFooter
em nossa classe:
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View style={styles.loading}>
<ActivityIndicator />
</View>
);
};
O resultado final deve ser algo como:
Concluindo
Esse post não possui scroll infinito, então acaba por aqui…
A utilização do scroll infinito se aplica muito bem a diversos tipos de projetos, veja que Instagram, Facebook, AirBnB e vários outros aplicativos que possuem um feed principal de alguma forma utilizam essa técnica para evitar processamento desnecessário.
Aplicar as técnicas de scroll infinito com Lazy Load e uma boa interface de pré-carregamento devem dar à sua aplicação um ar de acessibilidade bem mais limpa 🙂
Código do post: https://github.com/Rocketseat/blog-scroll-infinito-react-native
Se gostou do post, não esquece de deixar seu comentário!