У меня есть элементы меню с прокруткой, и заголовки каждого элемента жестко закодированы в константу вместе с идентификатором.
const list = [
{ name: "category1", id: 0 },
{ name: "category2", id: 1 },
{ name: "category3", id: 2 },
{ name: "category4", id: 3 },
{ name: "category5", id: 4 },
{ name: "category6", id: 5 },
{ name: "category7", id: 6 },
{ name: "category8", id: 7 }
];
У меня есть файл json, который содержит имя категории для каждого ребенка:
{
"results": [
{
"category": "category1",
"name": {
"title": "mr",
"first": "ernesto",
"last": "roman"
},
"email": "[email protected]",
"id": {
"name": "DNI",
"value": "73164596-W"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/73.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/73.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/73.jpg"
}
},
{
"category": "category2",
"name": {
"title": "mr",
"first": "adalbert",
"last": "bausch"
},
"email": "[email protected]",
"id": {
"name": "",
"value": null
} etc....
Я хочу показать эти категории "category": "category1", как заголовки моего меню, теперь мне нужно начать без сохранения состояния и добавить их из JSON, часть выборки из JSON выполняется локально в componentDidMount, но я не уверен, как я могу сопоставьте их с именами меню, чтобы сделать меню динамичным, я в основном хочу такой же вывод, но из json, не жестко запрограммированного. вот фрагмент песочницы, буду признателен за помощь.
https://codesandbox.io/s/2prw4j729p?fontsize=14&moduleview=1



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Просто преобразуйте вывод JSON в объект, например list, с функцией map из результатов, а затем установите как MenuItems в состоянии, которое вы передаете функции в render(). Как это.
import React, { Component } from "react";
import ScrollMenu from "react-horizontal-scrolling-menu";
import "./menu.css";
// One item component
// selected prop will be passed
const MenuItem = ({ text, selected }) => {
return (
<div>
<div className = "menu-item">{text}</div>
</div>
);
};
// All items component
// Important! add unique key
export const Menu = list =>
list.map(el => {
const { name, id } = el;
return <MenuItem text = {name} key = {id} />;
});
const Arrow = ({ text, className }) => {
return <div className = {className}>{text}</div>;
};
export class Menucat extends Component {
state = {
selected: "0",
MenuItems: []
};
componentDidMount() {
fetch("menu.json")
.then(res => res.json())
.then(result => {
const items = result.results.map((el, idx) => {
return { name: el.category, id: idx };
});
this.setState({
isLoaded: true,
MenuItems: items
});
});
}
render() {
const { selected, MenuItems } = this.state;
// Create menu from items
const menu = Menu(MenuItems, selected);
return (
<div className = "App">
<ScrollMenu
data = {menu}
selected = {selected}
onSelect = {this.onSelect}
alignCenter = {true}
tabindex = "0"
/>
</div>
);
}
}
export default Menucat;
Ваше здоровье!
Похоже, вам вообще не нужно жестко кодировать список категорий. В вашем componentDidMount() извлеките json и сгруппируйте результаты в отдельные категории следующим образом:
const json = {
"results": [
{
category: "category1",
name: "Fred"
},
{
category: "category1",
name: "Teddy"
},
{
category: "category2",
name: "Gilbert"
},
{
category: "category3",
name: "Foxy"
},
]
}
const grouped = json.results.reduce((acc, cur) => {
if (!acc.hasOwnProperty(cur.category)) {
acc[cur.category] = []
}
acc[cur.category].push(cur)
return acc;
}, { })
// parent object now has 3 properties, namely category1, category2 and category3
console.info(JSON.stringify(grouped, null, 4))
// each of these properties is an array of bjects of same category
console.info(JSON.stringify(grouped.category1, null, 4))
console.info(JSON.stringify(grouped.category2, null, 4))
console.info(JSON.stringify(grouped.category3, null, 4))
Обратите внимание, что этот json имеет 4 объекта в массиве результатов, 2 объекта категории 1 и 1 объекта категории 2 и категории 3. Вы можете запустить этот код в отдельном файле, чтобы увидеть, как он работает. Конечно, вы будете получать объект json с сервера. Я просто поставил его для демонстрации.
Затем установите состояние:
this.setState({ grouped })
Затем в render() вы показываете только категории, в которых есть такие элементы, как:
const menuBarButtons = Object.keys(this.state.grouped).map((category) => {
/* your jsx here */
return <MenuItem text = {category} key = {category} onClick = {this.onClick} blah = {blah}/>
/* or something , it's up to you */
})
Я предполагаю, что вы показываете элементы на основе текущей выбранной категории this.state.selected. Итак, после того, как вы визуализировали свое меню, вы должны сделать что-то вроде:
const selectedCatItems = this.state.grouped[this.state.selected].map((item) => {
return <YourItem name = {item.name} key = {item.id} blah = {blah} />
})
Затем сделайте это:
return (
<div className = "app">
<MenuBar blah = {blah}>
{menuBarButtons}
</Menubar>
<div for your item showing area>
{selectedCatItems}
</div>
</div>
)
Кроме того, не забудьте изменить свой onClick(), чтобы он правильно устанавливал состояние this.state.selected. Я верю, что вы можете понять это сами.
Надеюсь, поможет.
PS: я не писал полное решение для копирования/вставки для вашей проблемы просто потому, что я не хочу читать и понимать детали вашего пользовательского интерфейса и весь компонент для передачи данных компонента.
что, если в menu.json также есть подкатегория?