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



当我使用Form.Select时,从useState产品中获取值price时遇到一些问题。

这个想法是,使用Form.Select,您可以根据产品名称选择产品,然后onChangeProduct将使用给定的产品名称和该产品的价格属性设置data的状态。我只是不知道如何在用户不需要手动选择Form.Select中的价格的情况下获取price值。

这个代码是我收到的代码的简单说明。

如果你有任何组件可以让这件事变得比我更容易,我会很高兴听到它。

希望这是有道理的。

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和添加函数

CardForm.jsx->ModalEditProducts.jsx->产品编辑.jsx

CardForm.jsx中,我检查是否有ID,如果有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>
)}
</>
);
};

产品编辑.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>
);
};

首先,产品看起来是静态的,永远不会改变。因此,没有必要保持它们的状态,因为从来没有必要改变它们。你只需要在某个时刻发生变化时保持某种状态。您可以将它们保留在组件之外并引用它们。性能略有提高,但也向其他查看代码的人发出信号,表明它们是不可更改的和静态的。

其次,变更处理程序过于复杂。这里存储的不是对象数组,而是一个简单的选定值(选定项的名称(。React Bootstrap只在event中向您传递选项的value,而不是整个对象。由于该值只是一个普通字符串;基元";在JS中,您不需要担心任何不可变的状态更改。当您将字符串传递到函数中时,它们会被复制。但是,如果你只有名字,如何获得价格?

要获取价格,您可以使用所选名称查找相关选项并获取价格属性。find在这里是一个有用的工具。它允许您根据定义的一些真实性查找数组中的单个项。

你在你的问题中也建议将价格存储在状态中;你可能会想我为什么不这么做。实际上,在这里,您别无选择,因为库只传递给您optionvalue。然而,其他库会将整个选项传递给您。尽管如此,一般来说,只存储最低限度的数据来识别源数据中的选择是更好的,因为可以避免在保持项目与源数据同步方面出现一堆错误。在这里,你的期权数据没有变化并不重要,但这只是一个很好的实践。最好使用唯一标识符在规范源数据中查找它。

我还添加了一个默认的";请选择";选项默认状态首先选择这个(空字符串(

注意,在用户选择选项之前,price将是undefined,因为默认的""选项不会出现在products中。如果find遍历数组,并且根据传递的条件,它循环经过的项都不是真的,则返回undefined。

这就是为什么我在访问价格时在查找后使用?(可选链接(。否则你会出错。


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>
);
}

最新更新