Как создать страницу продукта с выпадающими списками вариантов в реакции?

Как лучше всего создать страницу продукта с раскрывающимися списками вариантов? У меня есть продукт со списком вариантов, например:

[{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 раскрывающихся списка: один для размера, один для цвета и один для материала, в котором перечислены все доступные параметры.

Мне нужен способ повлиять на два других раскрывающихся списка, когда один из раскрывающихся списков изменяется, чтобы в раскрывающихся списках были доступны только доступные варианты.

Например, если пользователь выбирает в первом раскрывающемся списке «маленький», в раскрывающемся списке цветов должен отображаться только красный цвет, а в раскрывающемся списке материалов — только металл и дерево.

Каков наилучший способ добиться этого?

Я создал пример 3 раскрывающихся списков в этом codeandbox: https://codesandbox.io/s/divine-water-vz8tv?file=/src/App.js


person poca    schedule 10.08.2020    source источник
comment
вам нужен контроллер для управления состоянием. это проще сделать с помощью хука useReducer   -  person Joe Lloyd    schedule 10.08.2020
comment
@JoeLloyd есть примеры?   -  person poca    schedule 11.08.2020


Ответы (1)


Вы можете собирать параметры каждый раз, когда значение одного из выбранных изменяется. Осталось только доработать сброс зависимых выборок при перевыборе основного (на setSize сброс color и material, на setColor сброс 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>
  );
}
person Nikita Madeev    schedule 10.08.2020