如何过滤列表然后分页过滤列表?

时间:2019-01-12 13:37:51

标签: reactjs pagination

我有一系列数据,这些数据在一个数组(json文件)中包含一些对象,它将由react显示。

class App extends React.Component {
constructor(props){
super(props);
this.state = {
data: [],
   .
   .
   .
currentPage: 1,
itemsPerPage: 20,
value: '',
filterTerm: null,
startIndex : 0,
endIndex : 4,
 }}}

[{'id': '5c0b6cd9e1382352759fbc25', 'hotelinfo': {'hotelsearch': {'realname': 'Korston Hotel Moscow'}},{'id': '5c0b6cd9e1382352759fbc24', 'hotelinfo': {'hotelsearch': {'realname': 'Lavanta Hotel'}},{'id': '5c0b6cd9e1382352759fbc28', 'hotelinfo': {'hotelsearch': {'realname': 'Stanpoli Hotel'}}]

有一个分页,默认情况下显示4页,然后单击下一步按钮显示其余页面。

render() {
 const { data, currentPage, itemsPerPage, startIndex, endIndex } = this.state;
 const indexOfLastItem = currentPage * itemsPerPage;
 const indexOfFirstItem = indexOfLastItem - itemsPerPage;
 const currentItemsOne = data.sort((a, b) => a.total - b.total);
 const currentItemsSecond = currentItemsOne.filter(this.filterData);
 const currentItems = currentItemsSecond.slice(indexOfFirstItem, indexOfLastItem);
 const renderHotel = currentItems.map((item, i) => {
    return <div class="item">
        <span>{item.hotelinfo.hotelsearch.realname}</span>
    </div>
});
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(data.length / itemsPerPage); i++) {
    pageNumbers.push(i);
}

const renderPageNumbers = pageNumbers.slice(startIndex, endIndex).map(number => {
    return (
        <li className={(this.state.currentPage === number ? 'active ' : '') + 'controls'}
            key={number}
            id={number}>
            {number}
        </li>
    )
});
return (
    <div>
        <input type="text" value={this.state.value}
            onChange={this.handleInputChange} class="hotelName" />
        <span onClick=this.handleSearch} class="searchbtn">search</span>
        { renderHotel }
        <ul id="page-numbers" class="pagenumDef">
            <li onClick={this.decremant} class="nexprev">
                <span class="fa-backward"></span></li>
            {renderPageNumbers}
            <li onClick={this.increment} class="nexprev"><span class="fa-forward"></span></li>
        </ul>
    </div >
)};

我有一个输入(class =“ hotelName”),用户开始输入该内容(例如,用户类型'Korston'),然后单击一个按钮,新结果应仅包含那些包含“ Korston”名称的酒店的数据。 / p>

handleInputChange(event) {
this.setState({ value: event.target.value });
}
handleSearch = () => {
let inputval = this.state.value
const { value } = this.state;
this.setState({ filterTerm: value });
}
filterData = (item) => {
const { filterTerm: term } = this.state;
if (term === null) {
    return true;
}
let inputval = this.state.value
inputval = term.toLowerCase()
    .split(' ')
    .map((s) => s.charAt(0).toUpperCase() + s.substring(1))
    .join(' ');

let realname = item.hotelinfo.hotelsearch.realname
let len = realname.length
if (len !== 0) {
    if (realname.includes(inputval)) {
        return true
    } else {
        return false
    }
}
return false;
}

我在任何页面中时如何过滤整个列表? 例如,第1页包含“莫斯科考斯顿酒店”的信息。在第2页中,“ Lavanta Hotelof”的信息。默认情况下,我在第1页中,键入“ Korston”或“ Lavanta”,结果显示给我“ Korston Hotel Moscow”或“ Lavanta Hotelof”的信息。但是,如果更改页面(例如,我在第2页中)并输入“ Korston”或“ Lavanta”,则不会有任何结果。 如何过滤列表然后对过滤后的列表进行分页?

修改

class App extends React.Component {
constructor(props){
super();
this.state = {
Library:[],
library: null,
perPage: 1,
currentPage: 1,
maxPage: null,
filter: "",
};

$.ajax({ 
url:"/json.bc", 
type:"post",
 data:{
  cityid:"1182348",
  rooms:JSON.stringify({"rooms":[{"adultcount":"1","childcountandage":"0"}]}),
    },
 success:(result)=>{ 
 this.setState({Library: eval(result)}); } 
 })
}

 componentDidMount() {
  this.reorganiseLibrary();
 }

 // Calculates the library
   reorganiseLibrary = () => {
   const { filter, perPage } = this.state;
   let library = Library;
   console.log(library)

  if (filter !== "") {
  library = library.filter(item =>
  item.hotelinfo.hotelsearch.realname.toLowerCase().includes(filter)
 );
 }

 library = _.chunk(library, perPage);
 this.setState({
  library,
  currentPage: 1,
  maxPage: library.length === 0 ? 1 : library.length
   });
  };

// Previous Page
   previousPage = () =>
   this.setState(prevState => ({
    currentPage: prevState.currentPage - 1
   }));

// Next Page
  nextPage = () =>
   this.setState(prevState => ({
   currentPage: prevState.currentPage + 1
  }));

 // handle filter
  handleFilter = evt =>
  this.setState(
   {
    filter: evt.target.value.toLowerCase()
  },
   () => {
   this.reorganiseLibrary();
  }
 );

// handle per page
   handlePerPage = (evt) =>
   this.setState({
    perPage: evt.target.value 
    }, () => this.reorganiseLibrary());

  // handle render of library
    renderLibrary = () => {
    const { library, currentPage } = this.state;
    if (!library || (library && library.length === 0)) {
     return <div>No results</div>;
     }
    return library[currentPage - 1].map(item => (
    <div key={item.hotelinfo.hotelsearch.realname}>
     {item.hotelinfo.hotelsearch.realname}</div>
      ));
    };

   render() {
    const { library, currentPage, perPage, maxPage } = this.state;
    return (
    <div className="library">
     <h1>Library</h1>
     <div className="d-flex">
      <div className="flex-fill">
          <label className="library__filter-label">Filter</label>
          <input value={this.state.filter} onChange={this.handleFilter} />
        </div>
      <div className="flex-fill text-right">
          <label className="library__per-page-label">Per page</label>
          <input placeholder="per page" value={this.state.perPage} onChange={this.handlePerPage} />
      </div>
  </div>
  <div className="library__book-shelf">
      {this.renderLibrary()}
  </div>
  <div className="d-flex">
      <div className="flex-fill">
        {currentPage !== 1 && (
          <button onClick={this.previousPage}>Previous</button>
        )}
      </div>
      <div className="flex-fill text-right">
        {(currentPage < maxPage) && (
          <button onClick={this.nextPage}>Next</button>
        )}
      </div>
  </div>
  <div className="library__page-info text-right">
      {this.state.currentPage} of {this.state.maxPage}
  </div>
      </div>)}};
       ReactDOM.render(<App/>, document.getElementById('root')); 

2 个答案:

答案 0 :(得分:1)

您使逻辑过于复杂。这是我在下面编写的示例和说明。

步骤1: 我们使用重组库函数加载库数据,该函数在安装组件,过滤器更改或编辑每页值时运行。

步骤2: 此功能将通过按perPage值将其拆分来计算图书馆中的数据块,然后计算最大页面值并将书籍列表设置为图书馆状态。

步骤3: 更改过滤器后,我们将在函数中执行另一段代码,该代码仅根据包含的字符串对书籍进行过滤,而字符串将仅过滤我们的书籍,从而仅将匹配的书籍设置为我们的图书馆状态。

const Library = [
  {
    name: "Star Wars"
  },
  {
    name: "Harry Potter"
  },
  {
    name: "Lord of the Rings"
  },
  {
    name: "Star Trek"
  },
  {
    name: "The Fault in Our Stars"
  },
  {
    name: "Number the Stars"
  },
  {
    name: "Blue"
  },
  {
    name: "Act Da Fool"
  },
  {
    name: "The Gilded Cage"
  },
  {
    name:
      "To Get to Heaven First You Have to Die (Bihisht faqat baroi murdagon)"
  },
  {
    name: "Lebanon"
  },
  {
    name: "Tenderness"
  },
  {
    name: "It"
  },
  {
    name: "Locked Out (Enfermés dehors)"
  },
  {
    name: "Waterloo Bridge"
  },
  {
    name: "Set It Off"
  },
  {
    name: "Nil By Mouth"
  },
  {
    name: "Monte Carlo"
  },
  {
    name: "Treasure of the Four Crowns"
  },
  {
    name: "Donnie Darko"
  },
  {
    name: "Cry-Baby"
  },
  {
    name: "Juan of the Dead (Juan de los Muertos)"
  },
  {
    name: "Constant Nymph, The"
  }
];

// Main App Component
class App extends React.Component {
  state = {
    library: null,
    perPage: 3,
    currentPage: 1,
    maxPage: null,
    filter: ""
  };

  componentDidMount() {
    this.reorganiseLibrary();
  }
  
  // Calculates the library
  reorganiseLibrary = () => {
    const { filter, perPage } = this.state;
    let library = Library;

    if (filter !== "") {
      library = library.filter(book =>
        book.name.toLowerCase().includes(filter)
      );
    }

    library = _.chunk(library, perPage);

    this.setState({
      library,
      currentPage: 1,
      maxPage: library.length === 0 ? 1 : library.length
    });
  };

  // Previous Page
  previousPage = () =>
    this.setState(prevState => ({
      currentPage: prevState.currentPage - 1
    }));

  // Next Page
  nextPage = () =>
    this.setState(prevState => ({
      currentPage: prevState.currentPage + 1
    }));
    
  // handle filter
  handleFilter = evt =>
    this.setState(
      {
        filter: evt.target.value.toLowerCase()
      },
      () => {
        this.reorganiseLibrary();
      }
    );
    
  // handle per page
  handlePerPage = (evt) =>
    this.setState({
      perPage: evt.target.value 
    }, () => this.reorganiseLibrary());

  // handle render of library
  renderLibrary = () => {
    const { library, currentPage } = this.state;
    if (!library || (library && library.length === 0)) {
      return <div>No results</div>;
    }
    return library[currentPage - 1].map(book => (
      <div key={book.name}>{book.name}</div>
    ));
  };

  render() {
    const { library, currentPage, perPage, maxPage } = this.state;
    return (
      <div className="library">
          <h1>Library</h1>
          <div className="d-flex">
              <div className="flex-fill">
                  <label className="library__filter-label">Filter</label>
                  <input value={this.state.filter} onChange={this.handleFilter} />
              </div>
              <div className="flex-fill text-right">
                  <label className="library__per-page-label">Per page</label>
                  <input placeholder="per page" value={this.state.perPage} onChange={this.handlePerPage} />
              </div>
          </div>
          <div className="library__book-shelf">
              {this.renderLibrary()}
          </div>
          <div className="d-flex">
              <div className="flex-fill">
                {currentPage !== 1 && (
                  <button onClick={this.previousPage}>Previous</button>
                )}
              </div>
              <div className="flex-fill text-right">
                {(currentPage < maxPage) && (
                  <button onClick={this.nextPage}>Next</button>
                )}
              </div>
          </div>
          <div className="library__page-info text-right">
              {this.state.currentPage} of {this.state.maxPage}
          </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.library {
  padding: 10px;
  margin: 10px;
  font-family: sans-serif;
}

.library__filter-label, .library__per-page-label {
  margin-right: 10px;
  text-transform: uppercase;
  font-size: 11px;
  font-weight: bold;
}

.library__book-shelf {
  padding: 10px;
  margin: 10px 0;
  border: 1px solid black;
} 

.library__page-info {
  margin-top: 20px;
}

.d-flex {
  display: flex;
}

.flex-fill {
  flex: 1 1;
}

.text-right {
  text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

一种可能的解决方案是为数据(您已经拥有)和filteredData分别设置状态值。对filteredData而不是数据运行分页。当用户更改除页码以外的任何过滤器时,请将state.currentPage重置为1,这样就永远不会看到空白结果。

当用户选择一个新的过滤器时,状态的变化。filteredData也应正确重置您的分页,因为它将重新绘制您的pageNumbers,从而导致renderPageNumbers也被重新绘制。

另一种解决方案是将分页结果包含在API本身而不是UI上,这样可以更可靠地使用您的信息。但是,如果您无法控制API,那当然不是有用的解决方案。