Почему useState не работает в этом сценарии

Я изучаю фронтенд-разработку и застрял на этой, казалось бы, очень простой проблеме, но не могу понять, почему она не работает.

Когда я нажимаю кнопку «Добавить в корзину», я хочу условно отображать ввод количества вместо кнопки (также попытаюсь сделать это по идентификатору, но это для другой темы).

Изображение на карточке товара для справки

Я написал этот код для компонента 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, сохраняя при этом старые значения, такие как идентификатор, имя и т. д., но это не работает.

похоже, что ваш список представляет собой массив, когда вы передаете новый объект.

Daniel A. White 06.08.2024 17:43

У вас есть массив ProductList, но когда вы его обновляете, вы превращаете его в объект, и компилятор справедливо жалуется на несоответствие. Измените {} на [].

Jared Smith 06.08.2024 17:44
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
2
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я кое-что заметил, первое здесь

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

Спасибо большое, проблема решена! Я возился с функцией карты, думая, что для обновления состояния мне нужно передать новый массив, но не смог понять синтаксис. Еще раз спасибо.

Darius Molotokas 06.08.2024 18:31

Другие вопросы по теме