diff --git a/src/pages/Chat/index.tsx b/src/pages/Chat/index.tsx
index a8959cc..670cc11 100644
--- a/src/pages/Chat/index.tsx
+++ b/src/pages/Chat/index.tsx
@@ -142,6 +142,27 @@ function ChatAdvertisementListItem({ advertisement, onClick }: ChatAdvertisement
);
}
+function ChatAdvertisementListItemSkeleton() {
+ return (
+
{rooms.map((room, index) => {
- const shouldRenderAdvertisement = (index + 1) % chatRoomSlotsPerAdvertisement === 0;
+ const shouldRenderAdvertisement =
+ chatRoomSlotsPerAdvertisement !== null && (index + 1) % chatRoomSlotsPerAdvertisement === 0;
const advertisement = shouldRenderAdvertisement
? advertisements[Math.floor(index / chatRoomSlotsPerAdvertisement)]
: undefined;
@@ -185,6 +209,9 @@ function ChatListPage() {
{advertisement && (
)}
+ {!advertisement && shouldRenderAdvertisement && isLoadingAdvertisements && (
+
+ )}
);
})}
diff --git a/src/pages/Club/ClubList/components/AdvertisementCard.tsx b/src/pages/Club/ClubList/components/AdvertisementCard.tsx
index 69f1ec4..8261106 100644
--- a/src/pages/Club/ClubList/components/AdvertisementCard.tsx
+++ b/src/pages/Club/ClubList/components/AdvertisementCard.tsx
@@ -34,4 +34,19 @@ function AdvertisementCard({ advertisement, onClick }: AdvertisementCardProps) {
);
}
+export function AdvertisementCardSkeleton() {
+ return (
+
+ );
+}
+
export default AdvertisementCard;
diff --git a/src/pages/Club/ClubList/index.tsx b/src/pages/Club/ClubList/index.tsx
index daa27e6..c36a5b0 100644
--- a/src/pages/Club/ClubList/index.tsx
+++ b/src/pages/Club/ClubList/index.tsx
@@ -3,7 +3,7 @@ import { useAdvertisementInterval } from '@/utils/hooks/useAdvertisementInterval
import { useAdvertisements } from '@/utils/hooks/useAdvertisements';
import { useInfiniteScroll } from '@/utils/hooks/useInfiniteScroll';
import useScrollRestore from '@/utils/hooks/useScrollRestore';
-import AdvertisementCard from './components/AdvertisementCard';
+import AdvertisementCard, { AdvertisementCardSkeleton } from './components/AdvertisementCard';
import ClubCard from './components/ClubCard';
import SearchBar from './components/SearchBar';
import { useGetClubs } from './hooks/useGetClubs';
@@ -29,8 +29,8 @@ function ClubList() {
itemCount: allClubs.length,
enabled: allClubs.length > 0,
});
- const advertisementCount = Math.floor(allClubs.length / clubSlotsPerAdvertisement);
- const { advertisements, trackAdvertisementClick } = useAdvertisements({
+ const advertisementCount = clubSlotsPerAdvertisement ? Math.floor(allClubs.length / clubSlotsPerAdvertisement) : 0;
+ const { advertisements, isLoadingAdvertisements, trackAdvertisementClick } = useAdvertisements({
advertisementCount,
scope: 'club-list',
});
@@ -45,7 +45,8 @@ function ClubList() {
{allClubs.map((club, index) => {
- const shouldRenderAdvertisement = (index + 1) % clubSlotsPerAdvertisement === 0;
+ const shouldRenderAdvertisement =
+ clubSlotsPerAdvertisement !== null && (index + 1) % clubSlotsPerAdvertisement === 0;
const advertisement = shouldRenderAdvertisement
? advertisements[Math.floor(index / clubSlotsPerAdvertisement)]
: undefined;
@@ -57,6 +58,9 @@ function ClubList() {
itemRef={index === 0 ? firstClubCardRef : index === 1 ? secondClubCardRef : undefined}
/>
{advertisement &&
}
+ {!advertisement && shouldRenderAdvertisement && isLoadingAdvertisements && (
+
+ )}
);
})}
diff --git a/src/utils/hooks/useAdvertisementInterval.ts b/src/utils/hooks/useAdvertisementInterval.ts
index f2becfc..be73929 100644
--- a/src/utils/hooks/useAdvertisementInterval.ts
+++ b/src/utils/hooks/useAdvertisementInterval.ts
@@ -1,4 +1,4 @@
-import { startTransition, useEffectEvent, useLayoutEffect, useState, type RefObject } from 'react';
+import { useEffectEvent, useLayoutEffect, useState, type RefObject } from 'react';
import { useLayoutElementsContext } from '@/contexts/useLayoutElementsContext';
const DEFAULT_ITEMS_PER_ADVERTISEMENT = 4;
@@ -26,7 +26,10 @@ export const useAdvertisementInterval = ({
enabled,
}: UseAdvertisementIntervalParams) => {
const { mainRef, bottomNavRef } = useLayoutElementsContext();
- const [itemsPerAdvertisement, setItemsPerAdvertisement] = useState
(DEFAULT_ITEMS_PER_ADVERTISEMENT);
+ const [itemsPerAdvertisement, setItemsPerAdvertisement] = useState(null);
+ const resetAdvertisementInterval = useEffectEvent(() => {
+ setItemsPerAdvertisement((previous) => (previous === null ? previous : null));
+ });
const measureAdvertisementInterval = useEffectEvent(() => {
const scrollContainer = mainRef.current;
@@ -44,28 +47,21 @@ export const useAdvertisementInterval = ({
? Math.max(0, secondItemRect.top - firstItemRect.top - firstItemRect.height)
: DEFAULT_ITEM_GAP;
const slotHeight = firstItemRect.height + gap;
-
- if (availableHeight <= 0 || slotHeight <= 0) {
- startTransition(() => {
- setItemsPerAdvertisement((previous) =>
- previous === DEFAULT_ITEMS_PER_ADVERTISEMENT ? previous : DEFAULT_ITEMS_PER_ADVERTISEMENT
- );
- });
- return;
- }
-
- const visibleSlotCount = Math.max(2, Math.floor((availableHeight + gap) / slotHeight));
- const nextItemsPerAdvertisement = Math.max(1, visibleSlotCount - 1);
-
- startTransition(() => {
- setItemsPerAdvertisement((previous) =>
- previous === nextItemsPerAdvertisement ? previous : nextItemsPerAdvertisement
- );
- });
+ const nextItemsPerAdvertisement =
+ availableHeight <= 0 || slotHeight <= 0
+ ? DEFAULT_ITEMS_PER_ADVERTISEMENT
+ : Math.max(1, Math.max(2, Math.floor((availableHeight + gap) / slotHeight)) - 1);
+
+ setItemsPerAdvertisement((previous) =>
+ previous === nextItemsPerAdvertisement ? previous : nextItemsPerAdvertisement
+ );
});
useLayoutEffect(() => {
- if (!enabled) return;
+ if (!enabled) {
+ resetAdvertisementInterval();
+ return;
+ }
let frameId = 0;
const scheduleMeasurement = () => {
@@ -73,7 +69,7 @@ export const useAdvertisementInterval = ({
frameId = window.requestAnimationFrame(measureAdvertisementInterval);
};
- scheduleMeasurement();
+ measureAdvertisementInterval();
const visualViewport = window.visualViewport;
const resizeObserver =
diff --git a/src/utils/hooks/useAdvertisements.ts b/src/utils/hooks/useAdvertisements.ts
index 86b2a24..d562c4a 100644
--- a/src/utils/hooks/useAdvertisements.ts
+++ b/src/utils/hooks/useAdvertisements.ts
@@ -29,9 +29,11 @@ export const useAdvertisements = ({ advertisementCount, scope }: UseAdvertisemen
const advertisements: Advertisement[] = advertisementQueries
.flatMap((query) => query.data?.advertisements ?? [])
.slice(0, advertisementCount);
+ const isLoadingAdvertisements = advertisementQueries.some((query) => query.isPending);
return {
advertisements,
+ isLoadingAdvertisements,
trackAdvertisementClick,
};
};