Migrate catalog giftConfiguration to useNitroQuery

The catalog's gift wrapping configuration was loaded by an effect in
useCatalog that fired GetGiftWrappingConfigurationComposer every time
the catalog opened, with the response stuffed into a catalogOptions
slice via setState-in-effect. Migrating to a TanStack query gives us
caching/dedup/loading-state for free on this one-shot session-stable
loader.

- New useGiftConfiguration() hook in src/hooks/catalog/ wraps the
  composer/parser pair with useNitroQuery and staleTime: Infinity
  (the wrapping config never changes within a session).
- CatalogGiftView now reads from the query directly instead of via
  catalogOptions; the useCatalog() call in that component is also
  dropped (no other field was used).
- useCatalog drops the GiftWrappingConfigurationEvent listener and the
  unconditional composer dispatch.
- ICatalogOptions loses the giftConfiguration? field — no remaining
  consumer.

First step toward the docs/ARCHITECTURE.md next-PR item 'Migrate
useCatalog read-only fetches to useNitroQuery'. The clubGifts loader
will follow once useNitroEventInvalidator lands (clubGifts can be
push-updated by the server after SelectClubGiftComposer, so it needs
cache invalidation, not just a one-shot fetch).
This commit is contained in:
simoleo89
2026-05-11 20:43:58 +02:00
parent f1af6fb68a
commit 8e4544c5aa
5 changed files with 34 additions and 20 deletions
+1
View File
@@ -2,3 +2,4 @@ export * from './useCatalog';
export * from './useCatalogFavorites';
export * from './useCatalogPlaceMultipleItems';
export * from './useCatalogSkipPurchaseConfirmation';
export * from './useGiftConfiguration';
+2 -15
View File
@@ -1,7 +1,7 @@
import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, CreateLinkEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetGiftWrappingConfigurationComposer, GetRoomEngine, GetSessionDataManager, GetTickerTime, GiftWrappingConfigurationEvent, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
import { BuildersClubFurniCountMessageEvent, BuildersClubPlaceRoomItemMessageComposer, BuildersClubPlaceWallItemMessageComposer, BuildersClubQueryFurniCountMessageComposer, BuildersClubSubscriptionStatusMessageEvent, CatalogPageMessageEvent, CatalogPagesListEvent, CatalogPublishedMessageEvent, ClubGiftInfoEvent, CreateLinkEvent, FrontPageItem, FurniturePlaceComposer, FurniturePlacePaintComposer, GetCatalogIndexComposer, GetCatalogPageComposer, GetClubGiftInfo, GetRoomEngine, GetSessionDataManager, GetTickerTime, GuildMembershipsMessageEvent, HabboClubOffersMessageEvent, LegacyDataType, LimitedEditionSoldOutEvent, MarketplaceMakeOfferResult, NodeData, ProductOfferEvent, PurchaseErrorMessageEvent, PurchaseFromCatalogComposer, PurchaseNotAllowedMessageEvent, PurchaseOKMessageEvent, RoomControllerLevel, RoomEngineObjectPlacedEvent, RoomObjectCategory, RoomObjectPlacementSource, RoomObjectType, RoomObjectVariable, RoomPreviewer, SellablePetPalettesMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useBetween } from 'use-between';
import { BuilderFurniPlaceableStatus, CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, DispatchUiEvent, FurniCategory, GetFurnitureData, GetProductDataForLocalization, GetRoomSession, GiftWrappingConfiguration, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, Offer, PageLocalization, PlacedObjectPurchaseData, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api';
import { BuilderFurniPlaceableStatus, CatalogNode, CatalogPage, CatalogPetPalette, CatalogType, DispatchUiEvent, FurniCategory, GetFurnitureData, GetProductDataForLocalization, GetRoomSession, ICatalogNode, ICatalogOptions, ICatalogPage, IPageLocalization, IProduct, IPurchasableOffer, IPurchaseOptions, LocalizeText, NotificationAlertType, Offer, PageLocalization, PlacedObjectPurchaseData, PlaySound, Product, ProductTypeEnum, RequestedPage, SearchResult, SendMessageComposer, SoundNames } from '../../api';
import { CatalogPurchaseFailureEvent, CatalogPurchaseNotAllowedEvent, CatalogPurchaseSoldOutEvent, CatalogPurchasedEvent, InventoryFurniAddedEvent } from '../../events';
import { useMessageEvent, useNitroEvent, useUiEvent } from '../events';
import { useNotification } from '../notification';
@@ -768,18 +768,6 @@ const useCatalogState = () =>
});
});
useMessageEvent<GiftWrappingConfigurationEvent>(GiftWrappingConfigurationEvent, event =>
{
const parser = event.getParser();
setCatalogOptions(prevValue =>
{
const giftConfiguration = new GiftWrappingConfiguration(parser);
return { ...prevValue, giftConfiguration };
});
});
useMessageEvent<MarketplaceMakeOfferResult>(MarketplaceMakeOfferResult, event =>
{
const parser = event.getParser();
@@ -1108,7 +1096,6 @@ const useCatalogState = () =>
{
if(!isVisible || rootNode) return;
SendMessageComposer(new GetGiftWrappingConfigurationComposer());
SendMessageComposer(new GetClubGiftInfo());
SendMessageComposer(new GetCatalogIndexComposer(currentType));
SendMessageComposer(new BuildersClubQueryFurniCountMessageComposer());
+29
View File
@@ -0,0 +1,29 @@
import { GetGiftWrappingConfigurationComposer, GiftWrappingConfigurationEvent } from '@nitrots/nitro-renderer';
import { UseQueryResult } from '@tanstack/react-query';
import { GiftWrappingConfiguration } from '../../api';
import { useNitroQuery } from '../../api/nitro-query';
/**
* Wraps the GetGiftWrappingConfigurationComposer / GiftWrappingConfigurationEvent
* request-response pair as a TanStack query. The configuration is
* session-stable (box types, ribbon types, colour palette) so the data
* is cached with `staleTime: Infinity` — the server is asked at most
* once per session.
*
* Replaces the previous pattern in useCatalog where the composer was
* dispatched eagerly inside an `isVisible` effect and the result was
* stored in `catalogOptions.giftConfiguration`. Consumers now read the
* query directly and benefit from the standard TanStack loading/error
* states.
*/
export const useGiftConfiguration = (
options: { enabled?: boolean } = {}
): UseQueryResult<GiftWrappingConfiguration> =>
useNitroQuery<GiftWrappingConfigurationEvent, GiftWrappingConfiguration>({
key: [ 'nitro', 'catalog', 'giftConfiguration' ],
request: () => new GetGiftWrappingConfigurationComposer(),
parser: GiftWrappingConfigurationEvent,
select: event => new GiftWrappingConfiguration(event.getParser()),
enabled: options.enabled,
staleTime: Infinity
});