В этой ситуации я пытаюсь использовать RTK-запрос с разными параметрами:
У меня есть корзина с несколькими товарами, каждый товар имеет счетчик для контроля количества купленного товара, поэтому я могу добавлять или удалять (увеличивать или уменьшать количество).
проблема:
хотя все счетчики имеют одинаковое определение запроса RTK, они используют триггер мутации и свойство isLoading, поэтому при нажатии на одну кнопку свойство isLoading переключается на true и отображает счетчики на всех других кнопках счетчиков.
Код компонента корзины:
const Cart = () => {
const {
isLoading,
isSuccess,
data: cart,
} = useGetCartQuery({ userId: userData.id });
const [addItem, { isLoading: isAddUpdating }] = useAddCartMutation();
const [removeItem, { isLoading: isRemoveUpdating }] = useRemoveCartMutation();
const handleAddBtn = (item: cartItemType) => {
if (item.product.availability > item.quantity) {
addItem({
userId: userData.id as string,
productId: item.product.id as string,
quantity: 1,
});
} else {
throw new Error("can't add more than items in stack");
}
};
const handleRemoveBtn = (item: cartItemType, count) => {
console.info(item, count);
if (item.quantity >= count) {
removeItem({
userId: userData.id as string,
productId: item.product.id as string,
count: count,
});
}
};
return (
<div>
<QCounter
availability = {item.product.availability}
count = {item.quantity}
handleAddBtn = {() => handleAddBtn(item)}
handleRemoveBtn = {() => handleRemoveBtn(item, 1)}
AddBtnLoading = {isAddUpdating}
RemoveBtnLoading = {isRemoveUpdating}
height = "36px"
width = "36px"
/>
</div>
);
};
Код QCounter:
const QCounter = ({
availability,
count,
handleAddBtn,
handleRemoveBtn,
AddBtnLoading,
RemoveBtnLoading,
height,
width,
}) => {
return (
<div>
<button
onClick = {handleRemoveBtn}
disabled = {count == 1 || RemoveBtnLoading}
>
{!RemoveBtnLoading ? (
"-"
) : (
<FaSpinner className = "animate-spin text-secondary" />
)}
</button>
<div>
<h3>{count}</h3>
</div>
<button
onClick = {handleAddBtn}
disabled = {count == availability || AddBtnLoading}
>
{!AddBtnLoading ? (
"+"
) : (
<FaSpinner className = "animate-spin text-secondary" />
)}
</button>
</div>
);
};
решения, которые я пробовал:
1- определить функцию запроса RTK для каждого элемента с помощью функции карты
я попытался определить их взамен с помощью функции карты, подобной этой
{cart.items.map((item: cartItemType) => {
const [addItem, { isLoading: isAddUpdating }] = useAddCartMutation();
const [removeItem, { isLoading: isRemoveUpdating }] = useRemoveCartMutation();
затем передайте addItem и isLoading каждому счетчику Qcounter, но я получил ошибку TS:
Хуки React должны вызываться в компоненте функции React или в пользовательской функции React Hook.
🤔 А знаете ли вы, что...
С React можно легко интегрировать с другими библиотеками и фреймворками.
Если я читаю и понимаю сообщение и код, вы, вероятно, сопоставляете cart
данные, возвращаемые из useGetCartQuery
в QCounter
в первом фрагменте, и хотите, чтобы каждый QCounter
имел свое собственное добавляющее/удаляющее «состояние» и индикатор.
Вы не можете вызывать мутации React-хуки в циклах или вложенных обратных вызовах, поскольку это нарушает Правила хуков. Я предлагаю переместить хуки мутации и добавить/удалить логику в компонент QCounter
, чтобы каждый элемент корзины имел собственное состояние и логику.
Пример:
Корзина:
const Cart = () => {
...
const {
isLoading,
isSuccess,
data: cart,
} = useGetCartQuery({ userId: userData.id });
return (
<div>
{cart.items.map((item: cartItemType) => (
<QCounter
key = {item.product.id}
item = {item}
userId = {userData.id}
height = "36px"
width = "36px"
/>
))}
</div>
);
};
QСчетчик:
interface QCounterProps {
item: cartItemType;
userId: string;
height: string;
width: string;
}
const QCounter = ({
height,
item,
userId,
width,
}: QCounterProps) => {
const [
addItem,
{ isLoading: isAddUpdating }
] = useAddCartMutation();
const [
removeItem,
{ isLoading: isRemoveUpdating }
] = useRemoveCartMutation();
const handleAddBtn = () => {
if (item.product.availability > item.quantity) {
addItem({
userId,
productId: item.product.id as string,
quantity: 1,
});
} else {
throw new Error("can't add more than items in stack");
}
};
const handleRemoveBtn = () => {
if (item.quantity > 0) {
removeItem({
userId,
productId: item.product.id as string,
count: item.quantity,
});
}
};
return (
<div>
<button
onClick = {handleRemoveBtn}
disabled = {item.quantity === 1 || isRemoveUpdating}
>
{isRemoveUpdating
? <FaSpinner className = "animate-spin text-secondary" />
: "-"
}
</button>
<div>
<h3>{item.quantity}</h3>
</div>
<button
onClick = {handleAddBtn}
disabled = {item.quantity === item.product.availability || isAddUpdating}
>
{isAddUpdating
? <FaSpinner className = "animate-spin text-secondary" />
: "+"
}
</button>
</div>
);
};