如何在 React TS 中为对象(Map 数据结构)中的每个项目渲染自定义元素?

发布于 2025-01-16 14:03:28 字数 1455 浏览 1 评论 0原文

我一直在使用此方法从数组中渲染多个自定义元素,但这是我第一次使用地图数据结构进行此操作。它编译得很好,但什么也不渲染。我在此处设置了一个codesandbox

import "./styles.css";
import React from "react";
import ImageGrid from "./ImageGrid";

interface OnlineImage {
  id: string;
  url: string;
}

export default function App() {
  const [onlineImages, setOnlineImages] = React.useState<Map<string, OnlineImage[]>>();
  
  React.useEffect(() => {
    let onlineImageMap = new Map<string, OnlineImage[]>();

    // fake api call
    onlineImageMap.set("randomImageSet1", [
      { id: "1", url: "https://picsum.photos/200" },
      { id: "2", url: "https://picsum.photos/200" }
    ]);
    onlineImageMap.set("randomImageSet2", [
      { id: "1", url: "https://picsum.photos/200" },
      { id: "2", url: "https://picsum.photos/200" }
    ]);

    // set state
    setOnlineImages(onlineImageMap);
  }, []);

  return (
    <div className="App">
      <div>Below should render my custom ImageGrid for each item in map...</div>
      <>
        {onlineImages?.forEach((imageSet, category) => {
          return (
            <>
              <div>Image Category: {category}</div>
              <ImageGrid images={imageSet} />
            </>
          );
        })}
      </>
    </div>
  );
}

I've been using this method to render multiple custom elements from an array but this is my first time doing it using a map data structure. It compiles fine but renders nothing. I've set up a codesandbox here.

import "./styles.css";
import React from "react";
import ImageGrid from "./ImageGrid";

interface OnlineImage {
  id: string;
  url: string;
}

export default function App() {
  const [onlineImages, setOnlineImages] = React.useState<Map<string, OnlineImage[]>>();
  
  React.useEffect(() => {
    let onlineImageMap = new Map<string, OnlineImage[]>();

    // fake api call
    onlineImageMap.set("randomImageSet1", [
      { id: "1", url: "https://picsum.photos/200" },
      { id: "2", url: "https://picsum.photos/200" }
    ]);
    onlineImageMap.set("randomImageSet2", [
      { id: "1", url: "https://picsum.photos/200" },
      { id: "2", url: "https://picsum.photos/200" }
    ]);

    // set state
    setOnlineImages(onlineImageMap);
  }, []);

  return (
    <div className="App">
      <div>Below should render my custom ImageGrid for each item in map...</div>
      <>
        {onlineImages?.forEach((imageSet, category) => {
          return (
            <>
              <div>Image Category: {category}</div>
              <ImageGrid images={imageSet} />
            </>
          );
        })}
      </>
    </div>
  );
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七色彩虹 2025-01-23 14:03:28

你好 Samuel:我认为你应该首先将映射转换为数组,然后使用 Array.prototype.map 方法,该方法实际上返回原始数组的副本,并应用了你的函数。

您可能已经发现 return 语句在 forEach 函数中不执行任何操作(更准确地说,它仅停止代码的执行,但不会将任何内容返回到外部上下文)。

如果您确实想使用 forEach,则必须使用数组或对象来捕获它,然后使用 Object.entries/.map 来迭代它


const myMap = new Map(Object.entries({a: 1, b: 2}))
const myMapCaptureList = []
myMap.forEach((value, key) => {
myMapCaptureList.push([key, value])
}
// then you can use myMapCaptureList
myMapCaptureList.map(([key, value]) => <div>{key}: <span>{value}</span></div>);

但我建议使用非常有用的 Array 更容易.from 方法可以帮助将 Map 转换为键/值对条目数组:[[key1, val1], [key2, val2]]。它本质上相当于运行Object.entries(someObject)

{Array.from(onlineImages || []).map(([category, imageSet]) => {
          return (
            <>
              <div>Image Category: {category}</div>
              <ImageGrid images={imageSet} />
            </>
          );
        })}

Hi Samuel: I think you should first convert the map to an Array and then use the Array.prototype.map method which actually returns a copy of the original array with your function applied to it.

As you probably already figured out the return statement does nothing within a forEach function (to be more exact it only stops the execution of the code but does not bring back anything into the outer context).

If you really want to use forEach you'll have to use an array or Object to catch it then use Object.entries/.map to iterate over it


const myMap = new Map(Object.entries({a: 1, b: 2}))
const myMapCaptureList = []
myMap.forEach((value, key) => {
myMapCaptureList.push([key, value])
}
// then you can use myMapCaptureList
myMapCaptureList.map(([key, value]) => <div>{key}: <span>{value}</span></div>);

But I would suggest that it is much easier to use the very helpful Array.from method that can help convert a Map into an array of key/value pair entries: [[key1, val1], [key2, val2]]. It is essentially equivalent to running Object.entries(someObject).

{Array.from(onlineImages || []).map(([category, imageSet]) => {
          return (
            <>
              <div>Image Category: {category}</div>
              <ImageGrid images={imageSet} />
            </>
          );
        })}
白昼 2025-01-23 14:03:28

您正在使用 .forEach 方法 - 该方法不返回任何内容,而是使用相同但确实返回内容的 .map

 {onlineImages?.map((imageSet, category) => 
        <>
          <div>Image Category: {category}</div>
          <ImageGrid images={imageSet} />
        </>
    )}

You are using the .forEach method - which returns nothing, instead use .map that is identical but does return things

 {onlineImages?.map((imageSet, category) => 
        <>
          <div>Image Category: {category}</div>
          <ImageGrid images={imageSet} />
        </>
    )}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文