diff --git a/src/app/admin/photos/page.tsx b/src/app/admin/photos/page.tsx index 2474f3d2..bbdbd868 100644 --- a/src/app/admin/photos/page.tsx +++ b/src/app/admin/photos/page.tsx @@ -12,7 +12,7 @@ import { pathForAdminPhotoEdit, } from '@/site/paths'; import { titleForPhoto } from '@/photo'; -import MorePhotos from '@/photo/MorePhotos'; +import MoreComponentsClient from '@/components/MoreComponentsClient'; import { getBlobPhotoUrlsNoStore, getPhotosCached, @@ -144,7 +144,10 @@ export default async function AdminPhotosPage({ )} {showMorePhotos && - } + } } /> diff --git a/src/app/og/page.tsx b/src/app/og/page.tsx index a9f9e2b8..d0d38d46 100644 --- a/src/app/og/page.tsx +++ b/src/app/og/page.tsx @@ -1,5 +1,5 @@ import { getPhotosCached, getPhotosCountCached } from '@/cache'; -import MorePhotos from '@/photo/MorePhotos'; +import MoreComponentsClient from '@/components/MoreComponentsClient'; import StaggeredOgPhotos from '@/photo/StaggeredOgPhotos'; import { PaginationParams, @@ -26,7 +26,10 @@ export default async function GridPage({ searchParams }: PaginationParams) { {showMorePhotos && - } + } ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 4f86b556..42e8ce81 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,19 +1,10 @@ -import { getPhotosCached, getPhotosCountCached } from '@/cache'; -import AnimateItems from '@/components/AnimateItems'; -import MorePhotos from '@/photo/MorePhotos'; -import SiteGrid from '@/components/SiteGrid'; +import { getPhotosCached } from '@/cache'; import { generateOgImageMetaForPhotos } from '@/photo'; -import PhotoLarge from '@/photo/PhotoLarge'; import PhotosEmptyState from '@/photo/PhotosEmptyState'; -import { - PaginationParams, - getPaginationForSearchParams, -} from '@/site/pagination'; -import { pathForRoot } from '@/site/paths'; import { Metadata } from 'next'; import { MAX_PHOTOS_TO_SHOW_OG } from '@/photo/image-response'; - -export const dynamic = 'force-static'; +import MoreComponents from '@/components/MoreComponents'; +import PhotosLarge from '@/photo/PhotosLarge'; export async function generateMetadata(): Promise { // Make homepage queries resilient to error on first time setup @@ -22,40 +13,24 @@ export async function generateMetadata(): Promise { return generateOgImageMetaForPhotos(photos); } -export default async function HomePage({ searchParams }: PaginationParams) { - const { offset, limit } = getPaginationForSearchParams(searchParams, 12); - - const [ - photos, - count, - ] = await Promise.all([ - // Make homepage queries resilient to error on first time setup - getPhotosCached({ limit }).catch(() => []), - getPhotosCountCached().catch(() => 0), - ]); - - const showMorePhotos = count > photos.length; +export default async function HomePage() { + // Make homepage queries resilient to error on first time setup + const photos = await getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_OG }) + .catch(() => []); return ( photos.length > 0 - ?
- - )} + ?
+ + { + 'use server'; + return ; + }} /> - {showMorePhotos && - } - />}
: ); diff --git a/src/components/MoreComponents.tsx b/src/components/MoreComponents.tsx new file mode 100644 index 00000000..534df222 --- /dev/null +++ b/src/components/MoreComponents.tsx @@ -0,0 +1,27 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +export default function MoreComponents({ + initialOffset = 1, + itemsPerRequest, + componentLoader, +}: { + initialOffset?: number + itemsPerRequest: number + componentLoader: (limit: number) => Promise +}) { + const [offset] = useState(initialOffset); + const [components, setComponents] = useState([]); + + useEffect(() => { + const getPhotosLargeComponentAsync = async () => { + return componentLoader(itemsPerRequest * offset); + }; + getPhotosLargeComponentAsync().then((component) => { + setComponents([component]); + }); + }, [componentLoader, itemsPerRequest, offset]); + + return components; +} diff --git a/src/photo/MorePhotos.tsx b/src/components/MoreComponentsClient.tsx similarity index 90% rename from src/photo/MorePhotos.tsx rename to src/components/MoreComponentsClient.tsx index c7902d5d..542ce57c 100644 --- a/src/photo/MorePhotos.tsx +++ b/src/components/MoreComponentsClient.tsx @@ -2,14 +2,16 @@ import { useRouter } from 'next/navigation'; import { useCallback, useEffect, useRef, useTransition } from 'react'; -import Spinner from '../components/Spinner'; +import Spinner from './Spinner'; -export default function MorePhotos({ +export default function MoreComponentsClient({ path, + label = 'Load more', triggerOnView = true, prefetch = true, }: { path: string + label?: string triggerOnView?: boolean prefetch?: boolean }) { @@ -59,7 +61,7 @@ export default function MorePhotos({ ? - : 'More photos'} + : label} ); } diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index fefb0b4e..49c560db 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -3,7 +3,7 @@ import PhotoSmall from './PhotoSmall'; import { clsx } from 'clsx/lite'; import AnimateItems from '@/components/AnimateItems'; import { Camera } from '@/camera'; -import MorePhotos from '@/photo/MorePhotos'; +import MoreComponentsClient from '@/components/MoreComponentsClient'; import { FilmSimulation } from '@/simulation'; import { GRID_ASPECT_RATIO, HIGH_DENSITY_GRID } from '@/site/config'; @@ -79,7 +79,10 @@ export default function PhotoGrid({
).concat(additionalTile ?? [])} /> {showMorePath && - } + } ); }; diff --git a/src/photo/PhotosLarge.tsx b/src/photo/PhotosLarge.tsx new file mode 100644 index 00000000..938c2db6 --- /dev/null +++ b/src/photo/PhotosLarge.tsx @@ -0,0 +1,25 @@ +import AnimateItems from '@/components/AnimateItems'; +import { Photo } from '.'; +import PhotoLarge from './PhotoLarge'; + +export default function PhotosLarge({ + photos, +}: { + photos: Photo[] +}) { + return ( + + )} + /> + ); +}