如何在 React 中创建带有变体下拉菜单的产品页面?

How to create a product page with variant dropdowns in react?

创建带有变体下拉菜单的产品页面的最佳方法是什么? 我有一个带有变体列表的产品,例如:

[{size: "small", color: "red", material: "metal"},
{size: "small", color: "red", material: "wood"},
{size: "medium", color: "blue", material: "plastic"},
{size: "large", color: "blue", material: "metal"},
{size: "large", color: "yellow", material: "wood"}]

我所做的是创建 3 个下拉菜单,一个用于大小,一个用于颜色,另一个用于 material,其中列出了所有可用选项。

我需要一种方法来在更改其中一个下拉菜单时影响其他 2 个下拉菜单,以便下拉菜单中只有可用的变体可用。

例如,如果用户从第一个下拉菜单中选择“小”,颜色下拉菜单应该只显示红色,material 下拉菜单应该只显示金属和木头。

实现此目标的最佳方法是什么?

我在这个codesandbox中创建了3个下拉菜单的例子: https://codesandbox.io/s/divine-water-vz8tv?file=/src/App.js

每次 select 之一的值发生变化时,您都可以收集选项。当 re-selecting 主要(在 setSize 重置 colormaterial,在 setColor 重置时,它仍然只是完成依赖 selects 的重置material).

Codesandbox

const products = [
  { size: "small", color: "red", material: "metal" },
  { size: "small", color: "red", material: "wood" },
  { size: "medium", color: "blue", material: "plastic" },
  { size: "large", color: "blue", material: "metal" },
  { size: "large", color: "yellow", material: "wood" }
];

export default function App() {
  const [size, setSize] = React.useState();
  const [color, setColor] = React.useState();
  const [material, setMaterial] = React.useState();

  const sizeOptions = products
    .map((p) => p.size)
    .filter((v, i, a) => a.indexOf(v) === i)
    .map((size) => ({ label: size, value: size }));
  const colorOptions = products
    .filter((p) => size && p.size === size.value)
    .map((p) => p.color)
    .filter((v, i, a) => a.indexOf(v) === i)
    .map((color) => ({ label: color, value: color }));
  const materialOptions = products
    .filter(
      (p) => size && p.size === size.value && color && p.color === color.value
    )
    .map((p) => p.material)
    .filter((v, i, a) => a.indexOf(v) === i)
    .map((material) => ({ label: material, value: material }));

  return (
    <div className="App">
      <Select value={size} onChange={setSize} options={sizeOptions} />
      <Select
        value={color}
        onChange={setColor}
        options={colorOptions}
        isDisabled={!size}
      />
      <Select
        value={material}
        onChange={setMaterial}
        options={materialOptions}
        isDisabled={!color}
      />
    </div>
  );
}