我使用React前端和express后端与PostgreSQL数据库。我想渲染大约8000行的大型json对象。当记录少于1000条时,网站运行良好,但随着记录数量的增加,它将无法呈现结果。Json对象的格式如下
[
{
book_name: "book 3",
id: 21598,
language: "urdu",
main_cat: "cat1 ",
media_link: [],
pg_no: 18,
riasat_ali_and_other: [],
room: "None",
search_cat: "poetry",
sinf: "taranay",
stage: "None",
sub_cat: "taranay",
tarzain: [],
title: "book_title1",
total: "1",
video: [],
written: ['link_to_img']
},
{
book_name: "book 3",
id: 21598,
language: "urdu",
main_cat: "cat1 ",
media_link: [],
pg_no: 18,
riasat_ali_and_other: [],
room: "None",
search_cat: "poetry",
sinf: "taranay",
stage: "None",
sub_cat: "taranay",
tarzain: [],
title: "book_title1",
total: "1",
video: [],
written: ['link_to_img']
}
]
QasaidPak用于将DB的结果呈现给前端,代码如下
import { Grid,Card } from '@material-ui/core';
import {connect} from 'react-redux';
import React, { Component, lazy } from 'react';
import './qasaid_pak.css'
const SearchHeader = lazy(() => import('../components/searchheader/Search.js'));
const QasidaMediaCard = lazy(() => import('../components/qasidamediacard'));
class QasaidPak extends Component{
state={
searchinput:'',
qasaid:[],
issorted:false
}
componentDidMount() {
// this.props.fetchQasaid()
this.setState({resultStatus:'true'})
};
renderQasaid(){
let i=0;
let qasaid=[]
if(this.state.issorted){
qasaid=this.state.qasaid
this.setState({issorted:false})
}
else{
qasaid=this.props.qasaid
}
return qasaid.map((qaseeda) => {
i+=1
return(<QasidaMediaCard key={qaseeda.id} id={i-1} qaseeda_pak={qaseeda}/>)})
}
GetSortOrder(prop) {
return function(a, b) {
if (a[prop] > b[prop]) {
return 1;
} else if (a[prop] < b[prop]) {
return -1;
}
return 0;
}
}
sortPage=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('pg_no')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
sortSinf=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('sinf')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
sortSubcat=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('sub_cat')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
sortCat=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('main_cat')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
sortLang=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('language')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
sortTitle=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('title')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
sortBook=()=>{
this.setState({qasaid:this.props.qasaid.sort(this.GetSortOrder('book_name')),issorted:true})
// array.sort(GetSortOrder("Experience"))
}
render(){
return(
<Grid container>
<Grid item xs={12} sm={12}>
<SearchHeader id='hidden-true'/>
</Grid>
<Grid xs={12} sm={12}>
<Card id="qasaid-header">
<Grid container className='row'>
<Grid item className='col' xs={1} sm={1} onClick={this.sortPage}>
<b>Written</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
<Grid item className='col' xs={1} sm={1} onClick={this.sortSinf} >
<b>Sinf</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
<Grid item className='col' xs={1} sm={1} onClick={this.sortSubcat}>
<b>Sub Category</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
<Grid item className='col' xs={2} sm={2} onClick={this.sortCat}>
<b>Main Category</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
<Grid item className='col' xs={1} sm={1} onClick={this.sortLang}>
<b>Language</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
<Grid item className='col' xs={5} sm={5} onClick={this.sortTitle}>
<b>Title</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
<Grid item className='col' xs={1} sm={1} onClick={this.sortBook}>
<b>Book</b>
<img src='https://icons.getbootstrap.com/assets/icons/sort-alpha-down.svg' width='17px' height='17px'></img>
</Grid>
</Grid>
</Card>
</Grid>
<Grid item id='poetry-results' xs={12} sm={12}>
{this.renderQasaid()}
</Grid>
</Grid>
)
};
}
const mapStateToProps=(state)=>{
const {qasaid}=state
console.log('Qasaid',qasaid)
return {qasaid}
}
export default connect(mapStateToProps)(QasaidPak);
qasidamediacard的代码如下
import React, { Component } from 'react';
import Grid from '@material-ui/core/Grid';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import RadioGroup from '@material-ui/core/RadioGroup';
import { AccordionSummary, Accordion,Container, Divider, Radio, AccordionDetails } from '@material-ui/core';
import Link from '@material-ui/core/Link';
import { FormControlLabel,TextField } from '@material-ui/core';
import Autocomplete from '@material-ui/lab/Autocomplete';
import {connect} from 'react-redux';
import ImgsViewer from "react-images-viewer";
import './mediacard.css';
// import ReactPlayer from 'react-player/youtube';
// import ReactPlayer from 'react-video-js-player';
import ReactWebMediaPlayer from 'react-web-media-player';
import { Media, Player } from 'react-media-player'
// const { PlayPause, MuteUnmute } = controls
class MediaCard extends Component{
render(){
return(
<Accordion className='root'>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id={(this.state.mediaLinkBool||
this.state.tarzainBool||
this.state.roomBool||
this.state.videoBool||
this.state.riasatAliBool||
this.state.stageBool)?"panel1a-header-data":"panel1a-header"}
>
<Grid container>
<Grid item className='col' xs={1} sm={1} onClick={this.pgClicked}>
<Link>
<b>{parseInt(this.state.qaseeda["pg_no"])}</b>
</Link>
</Grid>
<Grid item className='col' xs={1} sm={1}>
{this.state.qaseeda['sinf']}
</Grid>
<Grid item className='col' xs={1} sm={1}>
{this.state.qaseeda['sub_cat']}
</Grid>
<Grid item className='col' xs={2} sm={2}>
{this.state.qaseeda['main_cat']}
</Grid>
<Grid item className='col' xs={1} sm={1}>
{this.state.qaseeda['language']}
</Grid>
<Grid item xs={4} sm={4}>
<b>{(this.state.qaseeda.search_cat!='book')?(
this.state.qaseeda["title"]
):(
'...'+this.state.qaseeda["title"].split(' ').slice(0,12).join(' ')
)}</b>
</Grid>
<Grid item className='col' xs={2} sm={2}>
{this.state.qaseeda['book_name']}
</Grid>
</Grid>
</AccordionSummary>
<Divider></Divider>
<AccordionDetails id={this.state.qaseeda.search_cat+'-details'}>
{/* {this.state.qaseeda.search_cat!='book'} */}
{(this.state.qaseeda.search_cat!='book')?(
<Grid container>
<Grid id="mediaPlayer" item xs={6} sm={6}>
{this.state.medialink &&
<div>
{this.state.isYoutubeLink &&
<Media>
<div className="media">
<div className="media-player">
<Player src={this.state.medialink}/>
</div>
<div className="media-controls">
{/* <PlayPause />
<MuteUnmute /> */}
</div>
</div>
</Media>
}
{!this.state.isYoutubeLink &&
<div>
<ReactWebMediaPlayer
title={this.state.qaseeda["title_qaseda_pak"]}
audio={this.state.medialink}
/>
</div>
}
</div>
}
</Grid>
<Grid item className='meta' xs={6} sm={6}>
<RadioGroup className='radioGroup' value={this.state.version} onChange={this.handleVersionChange}>
<Container className='radioGroup'>
<FormControlLabel value='Tarzain' disabled ={(this.state.tarzainBool)?false:true} control={<Radio color="primary"/>} label="Tarzain" />
<FormControlLabel value='MediaLink' disabled ={(this.state.mediaLinkBool)?false:true} control={<Radio color="primary"/>} label="Media Link" />
<FormControlLabel value='RiasatAliAndOthers' disabled ={(this.state.riasatAliBool)?false:true} control={<Radio color="primary"/>} label="Riasat Ali And Others" />
<FormControlLabel value='Video' disabled ={(this.state.videoBool)?false:true} control={<Radio color="primary"/>} label="Video" />
<FormControlLabel value='RoomRec' disabled ={(this.state.roomBool)?false:true} control={<Radio color="primary"/>} label="Room" />
<FormControlLabel value='StageRec' disabled ={(this.state.stageBool)?false:true} control={<Radio color="primary"/>} label="Stage" />
{this.state.isComboBoxEnabled}
</Container>
<Container className='comboBox'>
{this.state.isComboBoxEnabled &&
<Autocomplete
className='combobox'
value={this.state.selectedValue}
onChange={this.comboBoxChange}
options={this.state.displayValues}
renderInput={(params) => <TextField placeholder="Click to select more audio / video" {...params} variant="outlined" />}
/>
}
</Container>
</RadioGroup>
</Grid>
</Grid>
):(
<div>
<p>
{this.state.qaseeda.title}
</p>
</div>
)
}
</AccordionDetails>
<ImgsViewer
imgs={this.state.imgSet['imgs']}
currImg={1}
isOpen={this.state.viewerIsOpen}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
onClose={()=>{
this.setState({viewerIsOpen:false})
}}
/>
</Accordion>
)
};
}
export default MediaCard;
Node应用程序运行良好,能够在几秒钟内提取数据,但渲染记录需要大量时间,有人能帮我解决这个问题吗?理想情况下,我希望能够在几秒钟内呈现所有8000个结果。期待您的宝贵建议。期待中的感谢。
当您有这么大的数据时,最好将其分部分显示出来。这意味着您可以一次请求数据,并在需要时在视图中显示。您应该使用react paginate。
npm install react-paginate --save
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import ReactPaginate from 'react-paginate';
// Example items, to simulate fetching from another resources.
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
function Items({ currentItems }) {
return (
<>
{currentItems &&
currentItems.map((item) => (
<div>
<h3>Item #{item}</h3>
</div>
))}
</>
);
}
function PaginatedItems({ itemsPerPage }) {
// We start with an empty list of items.
const [currentItems, setCurrentItems] = useState(null);
const [pageCount, setPageCount] = useState(0);
// Here we use item offsets; we could also use page offsets
// following the API or data you're working with.
const [itemOffset, setItemOffset] = useState(0);
useEffect(() => {
// Fetch items from another resources.
const endOffset = itemOffset + itemsPerPage;
console.log(`Loading items from ${itemOffset} to ${endOffset}`);
setCurrentItems(items.slice(itemOffset, endOffset));
setPageCount(Math.ceil(items.length / itemsPerPage));
}, [itemOffset, itemsPerPage]);
// Invoke when user click to request another page.
const handlePageClick = (event) => {
const newOffset = (event.selected * itemsPerPage) % items.length;
console.log(
`User requested page number ${event.selected}, which is offset ${newOffset}`
);
setItemOffset(newOffset);
};
return (
<>
<Items currentItems={currentItems} />
<ReactPaginate
breakLabel="..."
nextLabel="next >"
onPageChange={handlePageClick}
pageRangeDisplayed={5}
pageCount={pageCount}
previousLabel="< previous"
renderOnZeroPageCount={null}
/>
</>
);
}
// Add a <div id="container"> to your HTML to see the componend rendered.
ReactDOM.render(
<PaginatedItems itemsPerPage={4} />,
document.getElementById('container')
);
可能还有其他包,你可以在这里阅读它的文档。