如何在同一个组件中使用不同参数多次使用同一个 RTK 查询函数?

问题描述 投票:0回答:1

在这种情况下我尝试使用具有不同参数的 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.log(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>
  );
};

Q柜台代码:

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 Hook 函数中调用 React Hook。

reactjs redux redux-toolkit rtk-query
1个回答
0
投票

如果我正在阅读并理解帖子和代码,您可能会将从

cart
返回的
useGetCartQuery
数据映射到第一个片段中的
QCounter
,并希望每个
QCounter
都有自己的添加/删除“状态”和指示器。

您不能在循环或嵌套回调中调用突变 React hooks,因为这会破坏 Hooks 规则。我建议将突变挂钩和添加/删除逻辑移至

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>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.