【问题标题】:Rendering components based on prop type基于道具类型渲染组件
【发布时间】:2021-07-04 00:23:06
【问题描述】:

我有一个小型餐厅应用程序,可让用户从菜单中点餐。菜单分为三种:食物、饮料、甜点。从上到下的组件结构是 Order -> Menu -> MenuItem。我想根据类型分隔菜单页面(例如:所有食物都在名为 FOOD 的标题下,依此类推)。现在,Menu 组件从 Order 接收菜单数组作为道具,并为数组中的每个项目呈现 MenuItem。每个项目都有一个称为类型的属性。为简洁起见,我省略了与此问题无关的某些代码部分。

//顺序

export default function Order() {
  const [menu, setMenu] = useState<Array<{}>>([]);
  const [total, setTotal] = useState(0);

  useEffect(() => {
    apiFetch("menu").then((json) => setMenu(json.menu));
  }, []);


  async function handleSubmit(e: any) {
    e.preventDefault();
    const selectedItems = getSelectedItems(TotalStore);
    apiFetch("order", "post", { selectedItems })
      .then((json) => {
        alert("Order has been submitted");
        setTotal(0);
        TotalStore.reset();
        localStorage.setItem("last_order_id", json.order.id);

        function checkOrderStatus() {
          apiFetch(
            `order/${json.order.id || localStorage.getItem("last_order_id")}`
          ).then((placedOrder) => {
            const { order } = placedOrder;
            if (order[0].status === 2) {
              alert("Your order is ready!");
            } else {
              setTimeout(checkOrderStatus, 5000);
            }
          });
        }
        checkOrderStatus();
      })
      .catch((error) => {
        alert("Server error");
      });
  }

  function orderPlaced(total: number) {
    return total !== 0 ? true : false;
  }

  return (
    <div>
      {menu.length > 0 ? (
        <>
          <div className="menu">
            <div className="menu-title">Food Menu</div>
            <form id="menu-form" onSubmit={handleSubmit} autoComplete="off">
              <Menu onChange={itemChanged} props={menu} />
              <button type="submit" disabled={!orderPlaced(total)}>
                Place Order
              </button>
            </form>
          </div>
          <div className="order-total">
            <h2>
              Total: $<span>{total.toFixed(2)}</span>
            </h2>
          </div>
        </>
      ) : (
        <>Loading Menu</>
      )}
    </div>
  );
}

//菜单

export default function Menu({ onChange, props }: MenuProps) {
  return (
    <div>
      {props.map((food: any, index: number) => {
        return (
          <MenuItem
            key={index}
            onChange={onChange}
            type={food.type}
            item={food}
          />
        );
      })}
    </div>
  );
}

//菜单项

export default function MenuItem({ onChange, item, type }: MenuItemProps) {

  return (
    <div>
      <article className="menu-item" data-item-type={type}>
        <h3 className="item-name">{item.name}</h3>
        <input
          type="number"
          className="menu-item-count"
          min="0"
          value={data.count}
          onChange={menuItemCountChange}
        />
        <strong className="item-price">${item.price.toFixed(2)}</strong>
      </article>
    </div>
  );
}

这是页面当前的样子:

【问题讨论】:

  • 您想对列表中的某些项目进行分组吗?不太确定我是否理解您的问题。
  • 使用&lt;Menu onChange={itemChanged} {...menu} filter="food" /&gt; 之类的内容并使用props.filter 过滤您正在显示的菜单项。
  • 您要按food.type 对象属性分组吗?或者将菜单项 ararray.reduce 到他们预期的food.type 类别数组中?你的要求模棱两可。您能否澄清并提供所需的预期行为/输出?
  • 是的,我想根据菜单项的类型对它们进行分组。如果您现在查看页面,则没有什么可以区分食物饮料甜点。我想要一个

    或某种标签来分隔每个组,但由于我只有 MenuItem 来呈现所有菜单项,所以我不知道该怎么做。

  • 我不确定哪个部分在这里不清楚:任何普通菜单都有部分。在食物下,您会找到所有食物选项。在饮料下,您可以找到饮料。在 DESSERT 下,您会找到甜点。我附上的屏幕截图清楚地表明菜单没有这样的部分。问题是如何在适当的部分下呈现菜单项。该部分可以类似于

    。这是否太模糊或不清楚?

标签: javascript node.js reactjs


【解决方案1】:

您希望按food.type 属性对菜单数据进行分组。一种方法是将菜单项分类到它们的“食物类型”类别中,然后分别呈现每个组。

export default function Menu({ onChange, items }) {
  const foodCategories = items.reduce((categories, item) => {
    if (!categories[item.type]) {
      categories[item.type] = []; // <-- new array for category type
    }
    categories[item.type].push(item); // <-- push item into category type
    return categories;
  }, {});

  return (
    <div>
      {Object.entries(foodCategories).map(([type, foodItems]) => (
        <div key={type}>
          <h1>{type}</h1> // <-- category header
          {foodItems.map((food, index) => ( // <-- map food items
            <MenuItem
              key={index}
              onChange={onChange}
              type={food.type}
              item={food}
            />
          ))}
        <div>
      ))}
    </div>
  );
}

【讨论】:

    猜你喜欢
    • 2021-08-19
    • 2021-11-23
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2018-05-30
    • 1970-01-01
    相关资源
    最近更新 更多