如何遍历数组并使其仅返回少数元素,具体取决于 React 状态

How to iterate through an array of arrays and make it return only a handful of elements depending on React state

提问人:Pav 提问时间:5/9/2023 最后编辑:Pav 更新时间:5/9/2023 访问量:59

问:

我有一个包含其他数组的数组:

export const ArtifactArray = [
  AccessoriesArtifacts,
  BodyArtifacts,
  CloakArtifacts,
  FeetArtifacts,
  HandsArtifacts,
  HeadArtifacts,
  LeftHandArtifacts,
  MainHandArtifacts,
  NeckArtifacts
]

这些数组中的每一个都包含对象:

export const BodyArtifacts = [
  WonderArmor,
  BrimstoneBreastplate,
  PetrifiedWoodBreastplate,
  DragonScaleArmor,
  RibCage,
  GreatBasilistScales,
  TitansCuirass,
  CyclopsKingTunic,
];

稍后,我将遍历数组,并在屏幕上显示所有这些对象,如下所示:

{ArtifactArray.map((array, index) => (
  <Fragment key={index}>
    {array.map((artifact, index) => (
      <ArtifactsBlock
        key={index}
        src={artifact.pic}
        name={artifact.name}
      />
    ))}
  </Fragment>
))}

一切都按预期进行。

然后我尝试向它添加分页,这就是问题开始的地方。我只想每页返回 20 个对象(总共 120 个)。但是,如果这些数组中每个数组中没有相同数量的对象,我该怎么办?如果我使用array.slice(0, 20),array.slice(20, 40)等,在其中一些数组的末尾,它将返回11或9。当然,我可以摆脱那些内部数组,简单地将所有对象集中到一个数组中,但这太笨拙了。我想保持现在的样子。

JavaScript 数组循环 切片

评论

1赞 wonderflame 5/9/2023
请提供一个最小的可重现示例,以证明当其他人将其复制并粘贴到他们自己的 IDE 中时,您的问题,而没有任何其他问题。目前,您已添加许多未定义的对象。请考虑添加其中一些并删除其余的
0赞 Andy 5/9/2023
如果你使用的是 React,你可能想要添加该标签,这样可以获得更多的可见性。

答:

1赞 bebbi 5/9/2023 #1

把你的清单扁平化怎么样?

{ArtifactArray.flat().slice(i, i + pageLen).map(artifact, index) => (
  <ArtifactsBlock
    key={index}
    src={artifact.pic}
    name={artifact.name}
  />
)}
0赞 Andy 5/9/2023 #2

您可以将对象数组扁平化为一个数组,然后使用该数组的长度加上要显示的项目数的“限制”来确定如何对数据进行切片。

这是一个使用小型数据集(总共 11 个项目)的小工作示例。数据被展平并传递到组件中。有两种状态:一种用于页面,一种用于限制。注意:此处的限制设置为每页两个项目。

当呈现组件时,它会同时调用 和 函数。它们使用页面和限制状态中的信息构建一系列页面按钮和一系列工件。getPagesgetArtifacts

const { useState } = React;

function Example({ artifacts }) {

  const [ page, setPage ] = useState(0);
  const [ limit, setLimit ] = useState(2);

  // Return a subset of data from the artifacts state based
  // on the page number, and the page limit
  function getArtifacts() {
    return artifacts
      .slice(page * limit, (page * limit) + limit)
      .map(artifact => {
        return (
          <Artifact
            key={artifact.id}
            data={artifact}
          />
        );
      });
  }

  // Update the page state
  function handlePage(e) {
    const { dataset: { page } } = e.target;
    setPage(+page);
  }

  // Create a series of pages based on the number of objects
  // in the artifacts state, and the page limit. Add an active prop
  // to indicate which page button should be highlighted
  function getPages() {

    const arr = [];
    const mod = artifacts.length / limit;
    const pages = mod % limit === 0 ? mod : Math.floor(mod) + 1;

    for (let p = 0; p < pages; p++) {
      arr.push((
        <Page
          key={p}
          number={p}
          active={p === page}
          handlePage={handlePage}
        />)
      );
    }

    return arr;

  }

  // Get the pages and the artifacts
  return (
    <main>
      <h2>Artifacts</h2>
      <section className="pages">
        {getPages()}
      </section>
      <section className="artifacts">
        {getArtifacts()}
      </section>
    </main>
  );

}

// Return an artifact name
function Artifact({ data }) {
  return <section><h4>{data.name}</h4></section>;
}

// Return a page
function Page({ number, active, handlePage }) {
  
  const cn = ['page', active && 'active'].join(' ');
  
  return (
    <button
      className={cn}
      data-page={number}
      type="button"
      onClick={handlePage}
    >{number + 1}
    </button>
  );

}

const bodyArtifacts=[{id:"ba1",name:"WonderArmor"},{id:"ba2",name:"BrimstoneBreastplate"},{id:"ba3",name:"PetrifiedWoodBreastplate"},{id:"ba4",name:"DragonScaleArmor"},{id:"ba5",name:"GreatBasilistScales"},{id:"ba6",name:"TitansCuirass"},{id:"ba7",name:"CyclopsKingTunic"}];
const cloakArtifacts=[{id:"ca1",name:"RedCloak"},{id:"ca2",name:"BlueCloak"},{id:"ca3",name:"PinkCloak"},{id:"ca4",name:"GoldCloak"}];
const artifacts=[bodyArtifacts,cloakArtifacts];

const node = document.getElementById('root');
const root = ReactDOM.createRoot(node);

// Pass in the flattened data
root.render(<Example artifacts={artifacts.flat()} />);
.page { width: 30px; aspect-ratio: 1; border-radius: 5px;}
.page:not(:last-child) { margin-right: 0.25rem; }
.page:hover:not(.active) { background-color: #fffff0; cursor: pointer; }
.active { background-color: lightgreen; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"></div>