Я изучаю фронтенд-разработку и застрял на этой, казалось бы, очень простой проблеме, но не могу понять, почему она не работает.
Когда я нажимаю кнопку «Добавить в корзину», я хочу условно отображать ввод количества вместо кнопки (также попытаюсь сделать это по идентификатору, но это для другой темы).
Изображение на карточке товара для справки
Я написал этот код для компонента ProductCard:
import productList from "../data/productList";
import { useState } from "react";
function ProductCard() {
let quantityValue = 0;
let [newProductList, changeProductList] = useState(productList);
function revealQuantityInput(id: number) {
changeProductList({
...newProductList,
quantityVisibility: true,
});
}
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
alert("Form submitted correctly!");
}
return (
<>
{productList.map((item) => (
<div className = "p-6 mb-6 [&>*]:mb-4" key = {item.id}>
<img src = {item.image} />
<div
className = "bg-green-600 p-2"
onClick = {() => revealQuantityInput(item.id)}
>
{item.quantityVisibility ? (
<form onSubmit = {handleSubmit}>
<input
type = "number"
id = {"quantity" + item.id}
min = "1"
max = "9"
step = "1"
onChange = {(e) => (quantityValue = Number(e.target.value))}
className = "bg-gray-300 w-[150px] opacity-100 mr-3"
/>
<button className = "bg-gray-300" type = "submit">
Add to Cart
</button>
</form>
) : (
<p>Add to Cart</p>
)}
</div>
<p>{item.category}</p>
<p>{item.name}</p>
<p>{item.price}</p>
<p>{JSON.stringify(item.quantityVisibility)}</p>
</div>
))}
</>
);
}
export default ProductCard;
Это мой файл данных:
import productTypes from "../types/productTypes"
const productList:productTypes[] = [
{
id: 0,
image: "../../public/images/image-waffle-mobile.jpg",
name: "Waffle with Berries",
category: "Waffle",
price: 6.50,
quantityVisibility: false,
},
{
id: 1,
image: "../../public/images/image-creme-brulee-mobile.jpg",
name: "Vanilla Bean Crème Brûlée",
category: "Crème Brûlée",
price: 7.00,
quantityVisibility: false,
},
{
id: 2,
image: "../../public/images/image-macaron-mobile.jpg",
name: "Macaron Mix of Five",
category: "Macaron",
price: 8.00,
quantityVisibility: false,
},
{
id: 3,
image: "../../public/images/image-tiramisu-mobile.jpg",
name: "Classic Tiramisu",
category: "Tiramisu",
price: 5.50,
quantityVisibility: false,
},
{
id: 4,
image: "../../public/images/image-baklava-mobile.jpg",
name: "Pistachio Baklava",
category: "Baklava",
price: 4.00,
quantityVisibility: false,
},
{
id: 5,
image: "../../public/images/image-meringue-mobile.jpg",
name: "Pistachio Baklava",
category: "Baklava",
price: 4.00,
quantityVisibility: false,
},
]
export default productList
А это файл типов:
interface productTypes {
id: number;
image: string;
name: string;
category: string;
price: number;
quantityVisibility: boolean;
}
export default productTypes
Когда я пытаюсь обновить состояние в функции
revealQuantityInput
Я получаю эту ошибку:
Object literal may only specify known properties, and 'quantityVisibility' does not exist in type 'SetStateAction<productTypes[]>'.
Почему это может быть неопределенным?
Я пытаюсь обновить список данных, добавив новое значение TRUE, сохраняя при этом старые значения, такие как идентификатор, имя и т. д., но это не работает.
У вас есть массив ProductList, но когда вы его обновляете, вы превращаете его в объект, и компилятор справедливо жалуется на несоответствие. Измените {}
на []
.
Я кое-что заметил, первое здесь
function revealQuantityInput(id: number) {
changeProductList({
...newProductList,
quantityVisibility: true,
});
}
Ваше состояние представляет собой массив продуктов, и когда вы меняете список, он становится объектом, так и должно быть?
Затем в рендере вы используете ProductList, а не newProductList (который здесь инициализируется как ProductList).
Вам, вероятно, придется это сделать
function revealQuantityInput(id: number) {
changeProductList((prev) => prev.map((product) => {
if (product.id === id) {
return { ...product, quantityVisibility: true, };
}
return product;
});
}
Спасибо большое, проблема решена! Я возился с функцией карты, думая, что для обновления состояния мне нужно передать новый массив, но не смог понять синтаксис. Еще раз спасибо.
похоже, что ваш список представляет собой массив, когда вы передаете новый объект.