React - 选择基于其他选择的选项更改

时间:2021-07-16 15:51:14

标签: javascript reactjs ecmascript-6

我正在尝试添加当我选择颜色时的功能,它只显示该颜色的尺寸,然后当我选择尺寸时,它只给我这个尺寸的可用库存

我做了一个状态来存储所选颜色的值,但我不知道如何将它与该颜色的尺寸绑定,然后将尺寸与库存绑定!

// products.js

const products = [
  {
    _id: '1',
    name: 'Men solid drop shoulder neck regular fit pullover t-shirts',
    category: 'Man',
    subcat: 'Tshirt',
    type: 'Shoulder',
    fabric: '100% Cotton',
    price: 89.99,
    variants: [
        {   
            color:'black',
            sizes:[
                {
                   size:'S',
                   stock:3
                },
                {
                   size:'L',
                   stock:12,
                }
            ]
        },

        {   
            color:'white',
            sizes:[
                {
                   size:'M',
                   stock:8
                },
                {
                   size:'L',
                   stock:2
                },
                {
                   size:'XL',
                   stock:10
                }
            ]
        }
    ],


// Product.js

import  { useState } from 'react';
import { ListGroup, Row, Col, Card,Form, Button } from 'react-bootstrap'
const Product = ({product}) => {

const [colorState, setColorState] = useState('');

    return (
        <Card className="my-3 p-3 rounded">
          <Card.Text as='div'>
              <ListGroup.Item >
                <Row>
                  <Col>
                    <Form.Control as="select" onChange={(e)=> {
                      const selectedColor = e.target.value;
                      setColorState(selectedColor);

                    }} >
                      <option value="" disabled selected hidden>Color</option>
                      {product.variants.map(variant => <option value={variant.color}>{variant.color}</option>)}
                    </Form.Control>
                    {colorState}
                  </Col>
                  <Col>
                    <Form.Control as="select" 
                     >
                      <option value="" disabled selected hidden>Size</option>
                     {product.variants[0].sizes.map(sizes => <option value={sizes.size}>{sizes.size}</option>)} 
                    </Form.Control>

                    Quantity: <input type="number" name="points"  min='1' max={product.variants[0].sizes[0].stock}/>
                  </Col>

                </Row>
              </ListGroup.Item>
            </div>
          </Card.Text>
          <Button variant="primary">Purchase</Button>{' '}
        </Card>


    )
}

export default Product




3 个答案:

答案 0 :(得分:0)

您可以将产品组件更新为如下所示


const Product = ({product}) => {

const [colorState, setColorState] = useState('');
    return (
      <Card className="my-3 p-3 rounded">
          <Card.Text as='div'>
              <ListGroup.Item >
                <Row>
                  <Col>
                    <Form.Control as="select" onChange={(e)=> {
                      const selectedColor = e.target.value;
                      setColorState(selectedColor);

                    }} >
                      <option value="" disabled selected hidden>Color</option>
                      {product.variants.map(variant => <option value={variant.color}>{variant.color}</option>)}
                    </Form.Control>
                    {colorState}
                  </Col>
                  <Col>
                    <Form.Control as="select">
                      <option value="" disabled selected hidden>Size</option>
                      {product.variants.map(variant=> {
                        if(variant["color"] === colorState){
                          return variant.sizes.map(sizes => <option value={sizes.size}>{sizes.size}</option>)
                        }
                        return ""
                      })}
                    </Form.Control>
                    Quantity: <input type="number" name="points"  min='1' max={product.variants[0].sizes[0].stock}/>
                  </Col>

                </Row>
              </ListGroup.Item>
          </Card.Text>
          <Button variant="primary">Purchase</Button>{' '}
        </Card>
      )
}

export default Product

答案 1 :(得分:0)

类似于 Mohamed 的回答,但还添加了最大数量:

  const products = [
    {
      _id: "1",
      name: "Men solid drop shoulder neck regular fit pullover t-shirts",
      category: "Man",
      subcat: "Tshirt",
      type: "Shoulder",
      fabric: "100% Cotton",
      price: 89.99,
      variants: [
        {
          color: "black",
          sizes: [
            {
              size: "S",
              stock: 3
            },
            {
              size: "L",
              stock: 12
            }
          ]
        },

        {
          color: "white",
          sizes: [
            {
              size: "M",
              stock: 8
            },
            {
              size: "L",
              stock: 2
            },
            {
              size: "XL",
              stock: 10
            }
          ]
        }
      ]
    }
  ];
  //----------------------------------------------------
  const product = products[0];
  const [colorState, setColorState] = useState("");
  const [selectedSize, setSelectedSize] = useState("");
  return (
    <div className="App">
      <Card className="my-3 p-3 rounded">
        <Card.Text as="div">
          <ListGroup.Item>
            <Row>
              <Col>
                <Form.Control
                  as="select"
                  onChange={(e) => {
                    const selectedColor = e.target.value;
                    setColorState(selectedColor);
                  }}
                >
                  <option value="" disabled selected hidden>
                    Color
                  </option>
                  {product.variants.map((variant) => (
                    <option value={variant.color}>{variant.color}</option>
                  ))}
                </Form.Control>
                {colorState}
              </Col>
              <Col>
                <Form.Control
                  as="select"
                  onChange={(e) => {
                    setSelectedSize(e.target.value);
                  }}
                >
                  <option value="" disabled selected hidden>
                    Size
                  </option>
                  {product.variants.map((variant) => {
                    if (variant["color"] === colorState) {
                      return variant.sizes.map((sizes) => (
                        <option value={sizes.size}>{sizes.size}</option>
                      ));
                    }
                    return "";
                  })}
                </Form.Control>
                Quantity:
                {selectedSize && (
                  <input
                    type="number"
                    name="points"
                    min="1"
                    max={
                      product.variants[0].sizes.filter(
                        (size) => size.size === selectedSize
                      )[0].stock
                    }
                  />
                )}
              </Col>
            </Row>
          </ListGroup.Item>
        </Card.Text>
        <Button variant="primary">Purchase</Button>{" "}
      </Card>
    </div>
  );
}

答案 2 :(得分:0)

我会通过将所有输入字段(例如颜色、大小和数量)转换为受控组件来以稍微不同的方式执行此操作。因为,它让我可以更好地控制在更改颜色时更新/重置特定数量/大小,以及在单独更改大小时更新/重置数量。

此外,我将存储产品对象的选定变体,而不是仅存储颜色本身和相同的尺寸大小,而不是仅存储尺寸,我将存储选择的尺寸对象,通过它我将能够控制数量。

在所有这些更改之后,这就是我的 Product.js 的样子。

// Product.js

import { useState } from "react";
import { ListGroup, Row, Col, Card, Form, Button } from "react-bootstrap";

const Product = ({ product }) => {
  const defaultVariantObj = { color: "", sizes: [] };
  const [selectedVariant, setSelectedVariant] = useState(defaultVariantObj);
  const defaultSizeObj = { size: "", stock: 0 };
  const [selectedSize, setSelectedSize] = useState(defaultSizeObj);
  const defaultQuantity = 0;
  const [selectedQuantity, setSelectedQuantity] = useState(defaultQuantity);

  return (
    <Card className="my-3 p-3 rounded">
      <Card.Text as="div">
        <ListGroup.Item>
          <Row>
            <Col>
              <Form.Control
                as="select"
                onChange={(e) => {
                  const {
                    target: { value }
                  } = e;
                  setSelectedVariant(
                    product.variants.find(({ color }) => color === value) || {}
                  );
                  setSelectedSize(defaultSizeObj);
                  setSelectedQuantity(defaultQuantity);
                }}
                value={selectedVariant.color}
              >
                <option value="" disabled selected hidden>
                  Color
                </option>
                {product.variants.map((variant) => (
                  <option value={variant.color}>{variant.color}</option>
                ))}
              </Form.Control>
              {selectedVariant.color}
            </Col>
            <Col>
              <Form.Control
                as="select"
                onChange={(e) => {
                  const {
                    target: { value }
                  } = e;
                  setSelectedSize(
                    selectedVariant?.sizes.find(({ size }) => size === value) ||
                      {}
                  );
                  setSelectedQuantity(defaultQuantity);
                }}
                value={selectedSize.size}
              >
                <option value="" disabled selected hidden>
                  Size
                </option>
                {selectedVariant?.sizes?.map((sizeObj) => (
                  <option key={sizeObj.size} value={sizeObj.size}>
                    {sizeObj.size}
                  </option>
                ))}
              </Form.Control>
              Quantity:{" "}
              <input
                type="number"
                name="points"
                min={!selectedSize?.stock ? 0 : 1}
                max={selectedSize?.stock || 0}
                value={selectedQuantity}
                onChange={(e) => {
                  const {
                    target: { value }
                  } = e;
                  setSelectedQuantity(value);
                }}
              />
            </Col>
          </Row>
        </ListGroup.Item>
      </Card.Text>
      <Button variant="primary">Purchase</Button>{" "}
    </Card>
  );
};

export default Product;

这是沙盒的 Link。为了在沙箱中简单起见,我只使用了两个产品,以便处理多个产品(如果有)。