reactjs 如何使用www.example.com设置二维数组中选定值的状态form.select?

yxyvkwin  于 2022-12-26  发布在  React
关注(0)|答案(1)|浏览(95)

当我使用Form.Select时,从useState产品获取price值时遇到一些问题。
其思想是,使用Form.Select,您可以通过产品名称选择产品,然后onChangeProduct将使用给定的产品名称和该产品的price属性设置data的状态。我只是不确定如何获取price值,而无需用户在Form.Select中手动选择价格。
该代码是一个简单的说明代码,我得到了这么票价.
如果你有任何组件,将使这比我很高兴听到它更容易。
希望你能理解。

const [data, setData] = useState([]);

const [product, setProduct] = useState([
    { name: "TV", price: 1000 },
    { name: "Phone", price: 3000 },
  ]);

const onChangeProduct = (name, value) => {
   setData((prevValue) => {
      const newValues = [...prevValues];
      newValues = Object.assign({}, newValues, {[name]: value });
      return newValues;
   });
};

return (
<Form>
   <Form.Select
   onChange={(event) => {onChangeProduct("name", event.target.value);}}
   value={product.name}
   name="product"
   >
      {product.map((item) => {
         return <option value={item.name}>{item.name}</option>;
      })}
   </Form.Select>
</Form>
);
    • 编辑**

我决定用另一种方法来实现这一点,我可能需要将产品设置为一个数组/状态,因为我希望稍后能够同时获取价格和产品。
这个想法是使系统工作与添加/删除产品到一张卡,你将能够检查与产品名称和价格结帐。因此,你能够选择一个产品列表,并以这种方式看到该产品的价格属性。
我使用的函数与此处获得的函数相同:onChange, onProductRemove and add function
卡片表单. jsx-〉模态编辑产品. jsx-〉产品编辑. jsx
CardForm.jsx中,我检查是否有ID,如果有,我将获取该用户已经选择的所有产品。
CardForm.jsx

const CardForm = () => {
  const [data, setData] = useState({});

  const { id } = useParams();

  const [products, setProducts] = useState([]);

  useEffect(() => {
    if (id) {
      const fetchData = async () => {
        const docRef = doc(db, "user", id);
        try {
          const docSnap = await getDoc(docRef);
          setData(docSnap.data());
        } catch (error) {
          console.log(error);
        }
      };
      fetchData().catch(console.error);
    }
  }, []);

  const handleProductChanged = (product) => {
    setData((data) => ({ ...data, product }));
  };

  return (
    <>
      <Container className="mb-3 content_container_primary">
        <Row>
          <Col xs={12} md={12} lg={8} className="">
            <Form>
              <div className="box content_pa">
                <Col xs={12} md={12} lg={12}>
                  <div>
                    <ModalEditProducts
                      onProductChanged={handleProductChanged}
                      data={data.product ?? []}
                      title="Edit products"
                    />
                  </div>
                </Col>
              </div>
            </Form>
          </Col>
        </Row>
      </Container>
    </>
  );
};

ModalEditProducts.jsx

const ModalEditProducts = ({ title, data, onProductChanged }) => {
  const [show, setShow] = useState(false);
  const [newData, setNewData] = useState([]);

  useEffect(() => {
    setNewData(data);
  }, [data, show]);

  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  const handleProductChange = (index, name, value) => {
    setNewData((prevValues) => {
      const newValues = [...prevValues];
      newValues[index] = Object.assign({}, newValues[index], { [name]: value });
      return newValues;
    });
  };

  const handleProductAdded = () => {
    setNewData((prevValues) => [...prevValues, { product: "", price: 0 }]);
  };

  const handleProductRemoved = (index) => {
    setNewData((prevValues) => {
      const newValues = [...prevValues];
      newValues.splice(index, 1);
      return newValues;
    });
  };

  const handleSubmitProducts = (e) => {
    e.preventDefault();
    onProductChanged(newData);
    setShow(false);
  };

  return (
    <>
      <div className="content_header">
        <div className="content_header_top">
          <div className="header_left">Products</div>
          <div className="header_right">
            <Button className="round-btn" onClick={handleShow}>
              <i className="fa-solid fa-pencil t-14"></i>
            </Button>
          </div>
        </div>
      </div>

      {show && (
        <Modal show={show} onHide={handleClose} size="">
          <Modal.Header closeButton>
            <Modal.Title>{title}</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <ProductEdit
              data={newData}
              onProductChanged={handleProductChange}
              onProductAdded={handleProductAdded}
              onProductRemoved={handleProductRemoved}
            />
          </Modal.Body>
          <Modal.Footer>
            <Form>
              <Button
                className="btn-skill-complete"
                onClick={handleSubmitProducts}
              >
                Save
              </Button>
            </Form>
          </Modal.Footer>
        </Modal>
      )}
    </>
  );
};

ProductEdit.jsx

const ProductEdit = ({ data, onProductChanged, onProductRemoved, onProductAdded }) => {
  const [products, setProducts] = useState([]);

  useEffect(() => {
    GetProducts(setProducts);
  });

  return (
    {data.length > 0 ? (
        <Row>
          <Col xs={9} md={9}>
            <div className="product-modal-title mb-3">Pick a new product</div>
          </Col>
          <Col xs={3} md={3}>
            <div className="product-modal-title mb-3 text-center">
              Remove/add
            </div>
          </Col>
        </Row>
      ) : null}

      {data.length === 0 ? (
        <Col xs={12} md={12}>
          <Button
            className="btn-st-large t-16 "
            type="button"
            onClick={onProductAdded}
          >
            Add a product
          </Button>
        </Col>
      ) : (
        <>
          {data?.map((inputField, index) => (
            <div key={index}>
              <Row>
                <Col xs={9} md={9}>
                  <Form.Select
                    as={Col}
                    className="mb-3"
                    onChange={(event) => {
                      onProductChanged(index, "product", event.target.value);
                    }}
                    id="product"
                    name="product"
                    value={inputField.product}
                  >
                    <option>Choose product</option>
                    {products.map((item) => {
                      return (
                        <option key={item.id} value={item.name}>
                          {item.name} ({item.price} kr.)
                        </option>
                      );
                    })}
                  </Form.Select>
                </Col>
                <Col xs={3} md={3}>
                  <div className="btn-section">
                    <button
                      type="button"
                      className="round-btn"
                      onClick={onProductAdded}
                    >
                      <i className="fa-solid fa-plus"></i>
                    </button>
                    <button
                      type="button"
                      className="round-btn"
                      onClick={() => onProductRemoved(index)}
                    >
                      <i className="fa-solid fa-minus"></i>
                    </button>
                  </div>
                </Col>
              </Row>
            </div>
          ))}
        </>
      )}
    </Form>
  );
};
bhmjp9jg

bhmjp9jg1#

首先,产品看起来是静态的,永远不会改变。因此不需要保持它们的状态,因为永远不需要改变它们。你只需要在某个时候改变一些东西。你可以把它们放在组件之外并引用它们。性能上的微小改进,但也向其他看你代码的人发出信号,它们是不可改变的和静态的。
第二,修改处理程序过于复杂,这里你存储的不是一个对象数组,而是一个简单的选择值(所选项的名称)。React Bootstrap只在event中传递选项的value,而不是整个对象。由于该值只是一个普通字符串,在JS中被视为“原语”,你不需要担心任何不可变的状态改变,当你把字符串传递给函数时,它们被复制了,但是如果你只有名字,怎么得到价格呢?
为了得到价格,你可以使用这个名字来查找相关的选项,并得到价格属性。find是一个很有用的工具,它允许你根据你定义的一些真实性来查找数组中的单个项。
您在问题中建议也将价格存储在状态中;你可能会奇怪我为什么不这样做,实际上在这里你没有选择,因为库只给你optionvalue,但是其他库会给你整个选项,但是一般来说,只存储最小值来标识源数据中的选择更好,因为您避免了一系列与保持项与源数据同步有关的错误。在这里,你的期权数据在哪里没有改变并不重要,但这只是一个很好的实践,最好使用唯一的标识符在规范的源数据中查找它。
我还添加了一个默认的“请选择”选项。默认状态首先选择这个(空字符串)
注意:在用户选择选项之前,price将为undefined,因为默认的""选项不会出现在products中。如果find遍历数组,并且根据传递的条件,它所循环的项都不真实,则find返回undefined。
这就是为什么我在访问price时在find之后使用?optional chaining),否则会得到一个错误。

const products = [
    { name: "TV", price: 1000 },
    { name: "Phone", price: 3000 },
]

const MyForm = () => {
    const [selectedName, setSelectedName] = useState("");

    const price = products.find(product => product.name === selectedName)?.price

    return (
        <Form>
           <Form.Select
               onChange={(event) => {setSelectedName(event.target.value);}}
               value={selectedName}
           >
              <option value="">Select option...</option>
              {products.map((item) => {
                 return <option value={item.name}>{item.name}</option>;
              })}
           </Form.Select>
        </Form>
    );
}

相关问题