从JSON反应映射菜单

时间:2019-02-26 16:25:28

标签: javascript json reactjs web-applications jsx

我有一个滚动菜单项,每个项的标题都与id一起硬编码为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 :(得分:1)

看起来您根本不需要对类别列表进行硬编码。在您的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个对象,其中cat1的2个,cat 2和cat3的1个。您可以在单独的文件中运行此代码以查看其工作方式。当然,您将从服务器获取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:我之所以没有为您的问题写一个完整的复制/粘贴解决方案,仅仅是因为我不愿阅读和理解您的UI详细信息以及整个组件到组件数据传递的详细信息。

答案 1 :(得分:0)

只需使用结果中的list函数将JSON输出转换为类似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;

干杯!