首页 > 解决方案 > 如何在 ReactJs 中按属性过滤数量

问题描述

我正在尝试创建一个基于颜色、大小或两者的数量过滤器。例如,当我单击红色时,它会显示红色的全部数量,但如果我按红色和小号,它会显示我需要的确切数量。有没有办法做到这一点?

这就是我的意思。

在此处输入图像描述

当我选择颜色或尺寸时,应该显示数量。另外,我的错误不应该重复,因为图像上方列出了三种红色。

代码


import React, { useState } from "react";

export default function ControlledRadios() {
  const [qty, setQty] = useState(0);

  const data = [
    {
      id: 1,
      name: "Product A",
      attributes: [
        {
          id: 1,
          color: "Red",
          size: "Small",
          qty: 200,
        },
        {
          id: 2,      
          color: "Red",
          size: "Medium",
          qty: 100,
        },
        {
          id: 3,
          color: "Red",
          size: "Large",
          qty: 300,
        },
        {
          id: 4,
          color: "Yellow",
          size: "Small",
          qty: 200,
        },
        {
          id: 5,
          color: "Yellow",
          size: "Medium",
          qty: 100,
        },
        {
          id: 6,
          color: "Yellow",
          size: "Large",
          qty: 300,
        },
      ],
    },
  ];

  const handleChange = (event) => {
    setQty(event.target.value);
  };

  return (
    <>
      <h1>Quantity: {qty}</h1>
      <fieldset value={qty} onChange={(event) => handleChange(event)}>
        <h3>Color:</h3>
        {data?.map(({ attributes }) => {
          return attributes.map(({ id, ...rest }) => (
            <>
              <label key={id}>
                <input
                  type="radio"
                  name="schedule-weekly-option"
                  value={rest.qty}
                />
                {rest.color}
              </label>
              <br />
            </>
          ));
        })}
        <h3>Size:</h3>
        {data?.map(({ attributes }) => {
          return attributes.map(({ id, ...rest }) => (
            <>
              <label key={id}>
                <input
                  type="radio"
                  name="schedule-weekly-option"
                  value={rest.qty}
                />
                {rest.size}
              </label>
              <br />
            </>
          ));
        })}
      </fieldset>
    </>
  );
}

从数据值中可以看出,我有多种颜色和尺寸,例如{color: "Red", Size: "Small", qty: 200}我有多个红色值,所以应该添加每个红色,所以当我单击红色单选按钮时,它应该显示数量600,因为数量所有的红色都将被添加。但如果我按颜色 Red 和 size Small 它应该显示200

PS:如果可能的话,你能不能像我做的 3 色红色和黄色那样重复颜色,让它只有 1 红色和 1 黄色与尺寸相同。

如果您需要更多说明或解释,请在下方评论。谢谢

标签: javascriptarraysreactjsjsonfilter

解决方案


呸!这应该可以解决问题。这个想法是将更多数据传递给您的handleChange handleChange - 看看我是如何改变它的?我直接从目标元素中获取数据,这并不理想,但很有效。

我没有为你做过滤,祝你好运:) 应该只是.filter(...)在你的.map(...).

document.onreadystatechange = () => {
  const {useState} = React;

  function ControlledRadios() {
    const [qty, setQty] = useState(0);

    const data = [
      {
        id: 1,
        name: "Product A",
        attributes: [
          {
            id: 1,
            color: "Red",
            size: "Small",
            qty: 200,
          },
          {
            id: 2,      
            color: "Red",
            size: "Medium",
            qty: 100,
          },
          {
            id: 3,
            color: "Red",
            size: "Large",
            qty: 300,
          },
          {
            id: 4,
            color: "Yellow",
            size: "Small",
            qty: 200,
          },
          {
            id: 5,
            color: "Yellow",
            size: "Medium",
            qty: 100,
          },
          {
            id: 6,
            color: "Yellow",
            size: "Large",
            qty: 999,
          },
        ],
      },
    ];

    const handleChange = (event) => {
      const id = event.target.value;
      const targetAttribute = data[0].attributes.find(x => x.id == id);
      if (event.target.name === "schedule-weekly-option-color") {
        let sum = 0;
        data[0].attributes.forEach((a) => {
            if (a.color===targetAttribute.color) {
              sum += a.qty;
            }
        });
        setQty(sum);
      } else {
        let sum = 0;
        data[0].attributes.forEach((a) => {
            if (a.color===targetAttribute.color && a.size===targetAttribute.size) {
              sum += a.qty;
            }
        });
        setQty(sum);
      }
    };

    return (
      <React.Fragment>
        <h1>Quantity: {qty}</h1>
        <fieldset value={qty} onChange={(event) => handleChange(event)}>
          <h3>Color:</h3>
          {data.map(({ attributes }) => {
            return attributes.map(a => (
                <label key={a.id}>
                  <input
                    type="radio"
                    name="schedule-weekly-option-color"
                    value={a.id}
                  />
                  {a.color}
                </label>
            ));
          })}
          <h3>Size:</h3>
          {data.map(item => {
            return item.attributes.map(a => (
                <label key={a.id}>
                  <input
                    type="radio"
                    name="schedule-weekly-option-size"
                    value={a.id}
                  />
                  {a.size}
                </label>
            ));
          })}
        </fieldset>
      </React.Fragment>
    );
  }

  ReactDOM.render(<ControlledRadios />, document.body);
};
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>


推荐阅读