为什么Array.from(new Set)在React jsx中不起作用

问题描述 投票:4回答:1

我试图从GraphQL查询结果生成一个下拉选项,这是一个包含数组的对象。由于TypeScript不支持对象的迭代,我试图使用纯JavaScript来迭代数据。当我按照以下方式编写它时,它可以工作:

const unique = Array.from(
 new Set(data.PlayerDetails.map((item: any) => item.country))
);
console.log(unique);

但是当我把它放在JSX中时它不起作用。可能是什么原因?

...
return (
<p>
  <Bold>Players: </Bold>
  <select className="form-control">
    {Array.from(
      new Set(
        data.PlayerDetails.map((player: any) => {
          return (
            <option key={player.id} value={player.country}>
              {player.country}
            </option>
          );
        })
      )
    )}
  </select>
</p>
);

期待:在<option>...</option>删除重复。

实际结果:<option>...</option>仍然显示所有具有重复项的数据,但前一代码“unique”显示没有重复的数据。

javascript reactjs typescript
1个回答
2
投票

它与JSX无关,你在这些代码片段中做了两件截然不同的事情。

在您的第一个中,您通过将您的播放器条目映射到其国家/地区值并将其传递到Set以仅获取唯一的国家/地区值来消除重复项。

在创建<option>元素的代码中,您正在创建对象。这些将是独一无二的,因为每个对象都是唯一的,即使它具有相同的内容。

我的第一个想法是预先过滤播放器数据数组以删除重复项,然后将结果映射到<option>元素。例如:

const countries = new Set();
const uniquePlayers = data.PlayerDetails.filter(({country}) => {
    if (countries.has(country)) {
        return false;
    }
    countries.add(country);
    return true;
});
return (
    <select className="form-control">
    {uniquePlayers.map((player/*: any*/) => {
        return (
            <option key={player.id} value={player.country}>
              {player.country}
            </option>
        );
    })}
    </select>
);

实例:

const data = {
    PlayerDetails: [
        {
            id: 1,
            country: "China"
        },
        {
            id: 2,
            country: "USA"
        },
        {
            id: 3,
            country: "Finland"
        },
        {
            id: 1, // Duplicate
            country: "China"
        }
    ]
};

const Example = () => {
    const countries = new Set();
    const uniquePlayers = data.PlayerDetails.filter(({country}) => {
        if (countries.has(country)) {
            return false;
        }
        countries.add(country);
        return true;
    });
    return (
        <select className="form-control">
        {uniquePlayers.map((player/*: any*/) => {
            return (
                <option key={player.id} value={player.country}>
                  {player.country}
                </option>
            );
        })}
        </select>
    );
};

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<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>

...但实际上,您可以进行独特检查并在一次通过中创建<option>元素。从性能角度来看,你可能没有那么多的<option>元素,但它使代码更简单:

const options = new Map();
for (const player of data.PlayerDetails) {
    const {country} = player;
    if (!options.has(country)) {
        options.set(
            country,
            <option key={player.id} value={player.country}>
              {player.country}
            </option>
        );
    }
}
return (
    <select className="form-control">
    {options.values()}
    </select>
);

实例:

const data = {
    PlayerDetails: [
        {
            id: 1,
            country: "China"
        },
        {
            id: 2,
            country: "USA"
        },
        {
            id: 3,
            country: "Finland"
        },
        {
            id: 1, // Duplicate
            country: "China"
        }
    ]
};

const Example = () => {
    const options = new Map();
    for (const player of data.PlayerDetails) {
        const {country} = player;
        if (!options.has(country)) {
            options.set(
                country,
                <option key={player.id} value={player.country}>
                  {player.country}
                </option>
            );
        }
    }
    return (
        <select className="form-control">
        {options.values()}
        </select>
    );
};

ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>

<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>
© www.soinside.com 2019 - 2024. All rights reserved.