Quando aplico filtros, funciona apenas na primeira página dos itens. À medida que carrego mais itens, o filtro desaparece e tenho que clicar em filtro novamente, o que obviamente não é bom. Desejo clicar em Filtrar apenas uma vez e ele retornará todos os itens que correspondem aos critérios.
No momento, a API em que estou trabalhando tem apenas pouco mais de 200 itens. Devo apenas fazer três chamadas de API paginadas para baixar todos os itens na API e juntá-los em uma matriz mestre e, em seguida, filtrar dessa matriz mestre local? Dessa forma, ele exibirá todos os itens filtrados na página.
Mas digamos que eu tenha uma API com um banco de dados muito maior com alguns milhares de pontos de dados, então não quero carregar tudo no array local. Eu gostaria de saber como filtrar todos os itens paginados de uma vez e exibir apenas os itens filtrados.
Este é meu código:
import React, {Component} from 'react';
import axios from 'axios';
import BookList from './BookList';
import LoadingButton from './LoadingButton';
import FilterButton from './FilterButton';
const root_api = "...";
const books_per_page = 15;
class HomePage extends Component{
constructor(props){
super(props);
this.state ={
books:[],
pageNum: 1,
isLoading: false,
isDataFetched: false,
isListComplete: false,
error:''};
}
//get 15 items at a time
getBooks(){
const requestUrl = `${root_api}books?page=${
this.state.pageNum
}&per_page=${book_per_page}`;
this.setState({
isLoading: true
});
axios.get(requestUrl)
.then(res=>{
res.data.length > 0
? this.setState({
books: [...this.state.books, ...res.data],
isLoading: false,
isDataFetched: true,
pageNum: this.state.pageNum + 1
})
: this.setState({
isLoading: false,
isDataFetched: true,
isListComplete: true
});
})
.catch(err => {
console.log(err);
this.setState({
isLoading: false,
isDataFetched: false,
error: err.message
});
});
}
filterBooks(){
let newList =[];
let currentList = [];
currentList = this.state.books;
newList = currentList.filter(function(book){
return book.pages > 1200;
});
this.setState({books: newList});
}
render(){
return(
<div>
<FilterButton
isLoading={this.state.isLoading}
isListComplete={this.state.isListComplete}
clickHandler={()=>this.filterBooks()}
/>
{this.state.books.length > 0 &&(
<BookList books={this.state.books} />)}
<LoadingButton
isLoading={this.state.isLoading}
isListComplete={this.state.isListComplete}
clickHandler={()=>this.getBooks()}
/>
}
</div>
)
}}
Você não precisa criar uma matriz local mestre, apenas outra state
variável para controlar se o usuário deseja ou não que os livros sejam filtrados:
constructor(props){
super(props);
this.state ={
books:[],
pageNum: 1,
isLoading: false,
isDataFetched: false,
isListComplete: false,
error:'',
filtered: false // this is the new variable
};
}
Além de alterar algumas funções:
getBooks(){
const requestUrl = `${root_api}books?page=${
this.state.pageNum
}&per_page=${book_per_page}`;
this.setState({
isLoading: true
});
axios.get(requestUrl)
.then(res=>{
let newState = {
isDataFetched: true,
isLoading: false
}
if (res.data.length > 0) {
newState.pageNum = this.state.pageNum + 1
newState.books = [
...this.state.books,
...res.data
]
} else {
newState.isListComplete = true
}
this.setState(newState);
}).catch(err => {
console.log(err);
this.setState({
isLoading: false,
isDataFetched: false,
error: err.message
});
});
}
filterBooks(){
this.setState(prevState => ({
filtered: !prevState.filtered
}));
}
EDIT: E mude o método de renderização:
render() {
let bookListView
if (this.state.books.length > 0) {
let bookArr = this.state.books
if (this.state.filtered) {
bookArr = bookArr.filter(item => item.pages > 1200)
}
bookListView = <BookList books={bookArr} />
}
return(
<div>
<FilterButton
isLoading={this.state.isLoading}
isListComplete={this.state.isListComplete}
clickHandler={()=>this.filterBooks()}
/>
{bookListView}
<LoadingButton
isLoading={this.state.isLoading}
isListComplete={this.state.isListComplete}
clickHandler={()=>this.getBooks()}
/>
</div>
)
}
EDIT: Mudei a parte de filtragem para o render
método, se o seu usuário quiser filtrar seus resultados.
Este artigo é coletado da Internet.
Se houver alguma infração, entre em [email protected] Delete.
deixe-me dizer algumas palavras