显示子类数组中项目的DRY-er方法

时间:2018-11-28 23:10:17

标签: reactjs react-redux dry

我正在使用React和Redux创建一个菜单页面。目前,我在一组对象上拥有超过100个项目的整个菜单,其中包括食物类型(开胃菜,汉堡,甜点等)的“类别”属性

我最初只是映射所有项目,并像这样渲染它们:

render(){
    let foodList = this.props.foodMenu.map((food) => (
        <Food className="food-menu" key={food.id} food={food} addToCart={this.addToCart}/>
    ))

    return (
        <div >
            <h2>Food Menu</h2>
            {foodList}
        </div>
    )

但是,我希望能够按类别将菜单分开,这使我想到了这一点:

    render(){
    let appetizers = this.props.foodMenu.filter(food => food.category === 'appetizers').map((food) => (
        <Food className="food-menu" key={food.id} food={food} addToCart={this.addToCart}/>
    ))

    let soupsalad = this.props.foodMenu.filter(food => food.category === 'soupsalad').map((food) => (
        <Food className="food-menu" key={food.id} food={food} addToCart={this.addToCart}/>
    ))


    let steaks = this.props.foodMenu.filter(food => food.category === 'steaks').map((food) => (
        <Food className="food-menu" key={food.id} food={food} addToCart={this.addToCart}/>
    ))


    return (
        <div>
            <h2>Food Menu</h2>
            <h3>Appetizers</h3>
            <div className='container'>
                    {appetizers}
            </div>
            <h3>Soup or Salad</h3>
            <div className='container'>
                    {soupsalad}
            </div>
            <h3>Steak</h3>
            <div className='container'>
                    {steaks}
            </div>
        </div>

除3个类别外,我有12个。如您所见,这开始变得非常重复,而不是“ DRY”。我想知道是否有一种更清洁的方法可以做到这一点?

2 个答案:

答案 0 :(得分:1)

基于先前的回答,我决定为此制定一个切实可行的解决方案。我还添加了使用forEach方法执行此操作的另一种方法。请运行该代码段以查看结果。

干杯!

const Food = props => {
  //Do something that make sense with this :)
  const { food, addToCart, className } = props;
  return (
    <React.Fragment>
      Food: {food.id} <br />
    </React.Fragment>
  );
};

const App = props => {
  const categories = {
    Appetizers: "appetizers",
    Soupsalad: "soupsalad",
    Steaks: "steaks"
  };

  var menus1 = [];
  Object.keys(categories).forEach(categorie => {
    var subMenus = props.foodMenu
      .filter(food => food.category === categories[categorie])
      .map((food,i) => (
        <div key={i}>
          <h3>{categorie}</h3>
          <div className="container">
            <Food
              className="food-menu"
              key={food.id}
              food={food}
              addToCart={""}
            />
          </div>
        </div>
      ));
    menus1 = [...menus1, subMenus];
  });

  const menus2 = Object.entries(categories).map(e => {
    return props.foodMenu
      .filter(food => food.category === e[1])
      .map((food,i) => (
        <div key={i}>
          <h3>{e[0]}</h3>
          <div className="container">
            <Food
              className="food-menu"
              key={food.id}
              food={food}
              addToCart={""}
            />
          </div>
        </div>
      ));
  });

  return (
    <React.Fragment>
      <h2>Food Menu1 with foreach</h2>
      {menus1}

      <h2>Food Menu2 with map of map</h2>
      {menus2}
    </React.Fragment>
  );
};


var foodMenu = [
  { id: "food1", category: "appetizers" },
  { id: "food2", category: "soupsalad" },
  { id: "food3", category: "steaks" }
];
const rootElement = document.getElementById("root");
ReactDOM.render(<App foodMenu={foodMenu} />, rootElement);
<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>
<div id="root"/>

答案 1 :(得分:1)

@geostack发布了一个很好的答案。这也是我发现适用于我的应用程序的东西。

const sortByCategory = (dataArray) => {
    let sortedByCategory = {}
    dataArray.forEach(item => {
        if (sortedByCategory[item.category]) {
            sortedByCategory[item.category].push(item)
        } else {
            sortedByCategory[item.category] = []
            sortedByCategory[item.category].push(item)
        }
    })
    return sortedByCategory
}

render(){
    let sortedData = sortByCategory(this.props.foodMenu)
    let foodMenu = []

    for(let key in sortedData) {
        foodMenu.push(
            <div >
                <h3>{key.toUpperCase()}</h3>
                <br />
                <div>
                    {
                        sortedData[key].map(food => {
                            return (
                                <div key={food.id}>
                                    <Food  key={food.id} food={food} addToCart={this.addToCart}/>
                                    <hr />
                                </div>
                            )
                        })
                    }
                </div>
            </div>
        )
    }

    return (
        <div>
            {foodMenu}
        </div>
    )
}