如何在所有分页项目中应用过滤器,而仅显示过滤后的项目?

时间:2019-01-13 04:44:54

标签: javascript reactjs api pagination filtering

当我应用过滤器时,它仅在项目的第一页上起作用。当我加载更多项目时,过滤器消失了,必须再次单击“过滤器”,这显然不好。我只想单击一次过滤,它将返回所有符合条件的项目。

现在,我正在使用的API仅有200多个项目。我是否应该仅进行3个分页的API调用,以下载API中的所有项目并将它们加入主阵列,然后从该本地主阵列进行过滤?这样,它将在页面上显示每个过滤的项目。

但是,假设我有一个API,它的数据库更大,有数千个数据点,那么我不想将所有内容都加载到本地数组中。我想知道如何一次过滤所有分页的项目并仅显示过滤的项目。

这是我的代码:

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>
       )

}}

1 个答案:

答案 0 :(得分:1)

您无需创建主本地数组,只需创建另一个state变量即可跟踪用户是否希望过滤图书:

constructor(props){
    super(props);
    this.state ={
        books:[],
        pageNum: 1,
        isLoading: false,
        isDataFetched: false,
        isListComplete: false,
        error:'',
        filtered: false // this is the new variable
    };
}

以及更改一些功能:

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
    }));
}

编辑:并更改渲染方法:

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>
    )
}

编辑:我将过滤部分移到了render方法中,因此,如果您的用户想取消过滤其结果。