我有一系列数据,这些数据在一个数组(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'));
答案 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,那当然不是有用的解决方案。