Реагировать меню отображения из JSON - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть пункты меню с прокруткой, и заголовки каждого элемента жестко закодированы в const вместе с идентификатором

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": "ernesto.roman@example.com",
      "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": "adalbert.bausch@example.com",
      "id": {
        "name": "",
        "value": null
      } etc....

Я хочу показать эти категории "category": "category1", так как в заголовках моего меню мне теперь нужно начать без сохранения состояния и добавить их из JSON, часть выборки из JSON выполняется локальнов componentDidMount, но я не уверен, как я могу отобразить их так, чтобы они отображались как имена меню, чтобы сделать меню динамичным, я в основном хочу тот же вывод, но из json не жестко закодирован.вот фрагмент песочницы, буду признателен за помощь.

https://codesandbox.io/s/2prw4j729p?fontsize=14&moduleview=1

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Похоже, вам вообще не нужно жестко кодировать список категорий.В вашем 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.log(JSON.stringify(grouped, null, 4))

// each of these properties is an array of bjects of same category
console.log(JSON.stringify(grouped.category1, null, 4))
console.log(JSON.stringify(grouped.category2, null, 4))
console.log(JSON.stringify(grouped.category3, null, 4))

Обратите внимание, что этот json имеет 4 объекта в массиве результатов, 2 из cat1 и 1 из cat 2 и cat3.Вы можете запустить этот код в отдельном файле, чтобы увидеть, как он работает.Конечно, вы будете получать объект 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: Я не написал целое решение для копирования / вставки вашей проблемы просто потому, что неохотно читаю ипонять детали вашего пользовательского интерфейса и весь компонент для передачи данных компонента.

0 голосов
/ 26 февраля 2019

Просто преобразуйте вывод 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 } = el;
    const { 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;

Ура!

...