根据状态将组件动态添加到反应页面

时间:2020-06-12 13:39:59

标签: reactjs

所以我正在通过Udemy学习做出反应,并且讲师编写了此代码,以使用状态动态呈现汉堡成分的内容。基本上,他是将状态对象转换为数组,并使用该对象渲染东西。

import React from "react";
import classes from "./Burger.css";
import BurgerIngredient from "./BurgerIngredients/BurgerIngr";

const burger = (props) => {
  const transformedIngr = Object.keys(props.ingredients).map((igKey) => {
    return [...Array(props.ingredients[igKey])].map((_, i) => {
      return <BurgerIngredient key={igKey + i} type={igKey} />;
    });
  });

  return (
    <div className={classes.Burger}>
      <BurgerIngredient type="bread-top" />
      {transformedIngr}
      <BurgerIngredient type="bread-bottom" />
    </div>
  );
};

export default burger;

//Object.entries(props.ingredients).map((indexOne, indexTwo)

代码似乎非常复杂,即使多次观看同一视频,我也无法理解。我的意思是,我在网上进行了研究,发现有一种更好的方法可以使用

将对象转换为数组
Object.entries(props.ingredients)

任何人都可以向我解释现有代码吗,是否可以使用 Object.entries 使其变得更容易?或任何其他替代方法可以做到这一点?

BurgerBuilder.js

import React, { Component } from "react";
import Aux from "../../hoc/aux";
import Burger from "../../components/Burger/Burger";

class BurgerBuilder extends Component {
  state = {
    ingredients: {
      meat: 1,
      salad: 2,
      cheese: 1,
      bacon: 1,
    },
  };

  render() {
    return (
      <Aux>
        <Burger ingredients={this.state.ingredients} />
        <div>Controls</div>
      </Aux>
    );
  }
}

导出默认的BurgerBuilder;

BurgerIngriedent.js

import React, { Component } from "react";
import Classes from "./original.css";
import PropTypes from "prop-types";

class BurgerIngredients extends Component {
  render() {
    let ingredient = null;

    switch (this.props.type) {
      case "bread-bottom":
        ingredient = <div className={Classes.BreadBottom}></div>;
        break;
      case "bread-top":
        ingredient = (
          <div className={Classes.BreadTop}>
            <div className={Classes.Seeds1}></div>;
            <div className={Classes.Seeds2}></div>;
          </div>
        );
        break;
      case "meat":
        ingredient = <div className={Classes.Meat}></div>;
        break;
      case "salad":
        ingredient = <div className={Classes.Salad}></div>;
        break;
      case "cheese":
        ingredient = <div className={Classes.Cheese}></div>;
        break;
      case "bacon":
        ingredient = <div className={Classes.Bacon}></div>;
        break;
      default:
        ingredient = null;
        break;
    }
    return ingredient;
  }
}

BurgerIngredients.propTypes = {
  type: PropTypes.string.isRequired,
};

export default BurgerIngredients;

谢谢。

1 个答案:

答案 0 :(得分:3)

谁能向我解释现有代码

让我们从这一部分开始:

Object.keys(props.ingredients)

这用于将对象变成键数组。因此它将是一个带有['meat', 'salad', 'cheese', 'bread']的数组。

接下来,它将映射该字符串数组以将其转换为另一个数组。决定该新数组中内容的函数是:

(igKey) => {
    return [...Array(props.ingredients[igKey])].map((_, i) => {
      return <BurgerIngredient key={igKey + i} type={igKey} />;
    });
  }

要解压的第一部分是这个,目的是创建一个长度合适的数组:

[...Array(props.ingredients[igKey])]

props.ingredients[igKey]将获得与给定键关联的值。因此,如果密钥为'meat',则props.ingredients[igKey]1。或者,如果键为'salad',则值为2

有了这个数字,他们接下来拨打Array(1)(例如)。这将创建一个正确长度的数组。但是,有一个问题。由于数组构造函数的工作方式存在怪异,如果您尝试在此数组上调用.map,它将无法正常工作(您将无法更改值)。因此,为了解决这个问题,他们接下来要做的就是复制数组。这就是[... ]部分所做的。

现在我们有了一个数组,其长度等于对象中的值。最后要做的是在其上调用映射并创建一些组件。这就是这段代码的作用:

.map((_, i) => {
  return <BurgerIngredient key={igKey + i} type={igKey} />;
});

完成所有这些操作后,我们得到了一个二维数组。外部阵列的每种成分都有一个条目,内部阵列的成分等于该成分的数量。

是否可以使用Object.entries使其变得更容易?

我认为这不会带来任何重大变化。如果愿意,您可以将Object.keys(的使用替换为Object.entries(,但是在其他方面不会有太大变化。

或任何其他替代方法可以执行相同操作?

可以使用多种方式编写此代码。有些代码比给出的示例更具可读性,但是它们几乎都具有要完成的基本操作:将对象转换为数组,然后为该数组的每个元素创建一个右侧的数组长度,然后为每个内部数组创建一个组件。

这是一个带有显式for循环的示例,我发现它更具可读性:

const transformedIngr = [];
for (let igKey in props.ingredients) {
  const components = [];
  for (let i = 0; i < props.ingredients[igKey]; i++) {
    components.push(<BurgerIngredient key={igKey + i} type={igKey} />);
  }
  transformedIngr.push(components);
}