Я пытаюсь сгенерировать параметры раскрывающегося списка из результата запроса GraphQL, который представляет собой объект, содержащий массив. Поскольку TypeScript не поддерживает итерацию объектов, я пытался использовать чистый JavaScript для итерации данных. Когда я просто пишу это следующим образом, это работает:
const unique = Array.from(
new Set(data.PlayerDetails.map((item: any) => item.country))
);
console.info(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 [JS]](https://i.imgur.com/WsjO6zJb.png)


Это не имеет ничего общего с 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>