【问题标题】:Render data array as paginated components将数据数组渲染为分页组件
【发布时间】:2023-03-28 01:49:01
【问题描述】:

我是 React 新手,所以如果我弄错了术语,请原谅我。

我想创建一种对组件数组进行分页的方法。为此,我按照每页所需的项目数量对数组进行了切片,并将每页存储到一个 ne 数组中,例如:

const limit = 4
const numPages = 20
let pagewrapper = []

for (let i = 0; i < numPages; i++) {

  let start = i * limit
  let end = start + limit

  let pageItems = children.slice(start, end)

  // Skip first array push as 'page 1' is already showing.
  if (end != limit) {
    pagewrapper.push(<Grid gridContainerStyles={'grid-page__' + i} items={pageItems} />)
  }
}

然后我创建了一个简单的按钮来一次显示每个页面。

    <Button
      onClick={this.pagerHandleClick}
    >
      {'Show more'}
    </Button>

处理程序看起来像:

  pagerHandleClick() {
    this.setState(state => ({
      page: state.page + 1,
    }))
  }

但是从这里我有点卡住了。我不知道如何告诉每个&lt;Grid /&gt; 来展示它的自我。我谷歌的所有解决方案似乎都表明将组件包装在 if 语句中,但是将每个数组项包装在它自己的 if 语句中似乎很奇怪。

在过去,我会在 Vanilla JS 或 JQuery 中使用简单的 getElementByClass. 完成此操作,但我不知道在 React 中是否可以通过这种方式实现。

有人可以在这里为我指出正确的方向吗?

非常感谢

【问题讨论】:

  • @YevgenGorbunkov,我接受给我的绝大多数答案,但我对自己有一个规则,在我为自己正确测试之前我不接受答案。我不想意外地接受不会帮助其他可能在未来发现这个问题的人的答案。我绝对不是说你的答案是错误的,只是由于我目前的工作性质,我还没有能够测试或使用它。

标签: javascript reactjs


【解决方案1】:

假设您一次获得所有数据(例如从 API 获取)并且只需要呈现其中的一部分,您可以简单地动态切片源数据数组,在组件状态中跟踪您的当前页面(例如页面长度5 项):

const [data, setData] = useState([]),
      [page, setPage] = useState(0),
      maxPage = Math.ceil(data.length/5),
      onNextPage = () => setPage((page+1)%maxPage),
      onPrevPage = () => setPage((page+5-1)%maxPage)
<Grid container>
        {
          data
            .slice(page*5,5*(page+1))
            .map((content,key) => (
              <Grid item {...{key}}>
                <Paper className="paper">{content}</Paper>
              </Grid>
            ))
        }
</Grid>

您可能想查看以下演示以获取完整示例(我猜您一直在使用 material-ui 来设置组件样式):

//dependencies
const { render } = ReactDOM,
      { useState, useEffect } = React,
      { Button, Paper, Grid, LinearProgress } = MaterialUI,
      { get } = axios

//paginated output, by default 5 items per page
const PaginatedBoard = () => {

  //initiate state and event handlers
  const [data, setData] = useState([]),
        [page, setPage] = useState(0),
        maxPage = Math.ceil(data.length/5),
        onNextPage = () => setPage((page+1)%maxPage),
        onPrevPage = () => setPage((page+5-1)%maxPage)
        
  //fetch src data on component render
  useEffect(() => get('https://api.nytimes.com/svc/topstories/v2/science.json?api-key=k9DaUAw5wUAei4J5WXRsy3EL988RADE3').then(({data:{results}}) => setData(results.map(({abstract}) => abstract))),[])
  
  //return components body
  return data.length ?
      (<div>    
        <Grid container spacing="2" >
          {
            data
              .slice(page*5,5*(page+1))
              .map((content,key) => (
                <Grid item {...{key}}>
                  <Paper className="paper">{content}</Paper>
                </Grid>
              ))
          }
        </Grid>
              <div>
                <Button onClick={onPrevPage} disabled={!page}>&lt;Prev</Button>
                <Button onClick={onNextPage} disabled={page==Math.ceil(data.length/5)-1}>Next&gt;</Button>
              </div>

      </div>) : 
      <LinearProgress style={{margin:'70px',width:'50%'}} />
}

//render
render (
  <PaginatedBoard />,
  document.getElementById('root')
)
.grid {
  width:70%;
  margin:auto;
}

.paper {
  width:100px;
  height:145px;
  overflow:hidden;
}
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"&gt;&lt;/script&gt;&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"&gt;&lt;/script&gt;&lt;script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.development.js"&gt;&lt;/script&gt;&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.1/axios.min.js"&gt;&lt;/script&gt;&lt;div id="root"&gt;&lt;/div&gt;

【讨论】:

    【解决方案2】:

    您可以将 for 循环包装在要显示网格的 html(React)中, 像这样:

    创建大小为 numPages 的数组:

    let elements = new Array(numPages);
    

    然后在按钮附近的某处添加以下内容:

    <div>
    {elements.map((entry, i) => {
    let start = i * limit
      let end = start + limit
    
      let pageItems = children.slice(start, end)
    
      // Skip first array push as 'page 1' is already showing.
      if (end != limit) {
        return (<Grid gridContainerStyles={'grid-page__' + i} items={pageItems} />)
    
      }
    return ''
    })}
    
    </div>
    

    【讨论】:

      【解决方案3】:

      您可以根据您的页面状态呈现子项的数量。

      const pagesToShow = Array.from({ length: pages }); // it will create new array on which will map
      pagesToShow.map((_, index) => {
        const PageItems = children.slice(limit*index, limit*index + limit);
        <Grid gridContainerStyles={'grid-page__' + i} items={pageItems} />
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-16
        • 2017-06-16
        • 2018-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-29
        相关资源
        最近更新 更多