Fix duplicate photo keys in development
This commit is contained in:
parent
bb58c91977
commit
ff6165a19b
@ -1,5 +1,5 @@
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { HTMLAttributes, JSX, RefObject } from 'react';
|
||||
import { HTMLAttributes, ReactNode, RefObject } from 'react';
|
||||
|
||||
/*
|
||||
MAX WIDTHS
|
||||
@ -22,8 +22,8 @@ export default function SiteGrid({
|
||||
}: {
|
||||
containerRef?: RefObject<HTMLDivElement | null>
|
||||
className?: string
|
||||
contentMain: JSX.Element
|
||||
contentSide?: JSX.Element
|
||||
contentMain: ReactNode
|
||||
contentSide?: ReactNode
|
||||
sideFirstOnMobile?: boolean
|
||||
sideHiddenOnMobile?: boolean
|
||||
} & HTMLAttributes<HTMLDivElement>) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { SHOULD_PREFETCH_ALL_LINKS } from '@/app/config';
|
||||
import { JSX } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import Spinner from './Spinner';
|
||||
import LinkWithLoader from './LinkWithLoader';
|
||||
|
||||
@ -15,7 +15,7 @@ export default function SwitcherItem({
|
||||
noPadding,
|
||||
prefetch = SHOULD_PREFETCH_ALL_LINKS,
|
||||
}: {
|
||||
icon: JSX.Element
|
||||
icon: ReactNode
|
||||
title?: string
|
||||
href?: string
|
||||
className?: string
|
||||
|
||||
@ -11,8 +11,8 @@ import { TAG_HIDDEN } from '@/tag';
|
||||
import HiddenHeader from '@/tag/HiddenHeader';
|
||||
import FocalLengthHeader from '@/focal/FocalLengthHeader';
|
||||
import PhotoHeader from './PhotoHeader';
|
||||
import { JSX } from 'react';
|
||||
import RecipeHeader from '@/recipe/RecipeHeader';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export default function PhotoDetailPage({
|
||||
photo,
|
||||
@ -38,7 +38,7 @@ export default function PhotoDetailPage({
|
||||
shouldShare?: boolean
|
||||
includeFavoriteInAdminMenu?: boolean
|
||||
} & PhotoSetCategory) {
|
||||
let customHeader: JSX.Element | undefined;
|
||||
let customHeader: ReactNode | undefined;
|
||||
|
||||
if (tag) {
|
||||
customHeader = tag === TAG_HIDDEN
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
INFINITE_SCROLL_FEED_INITIAL,
|
||||
INFINITE_SCROLL_FEED_MULTIPLE,
|
||||
Photo,
|
||||
} from '.';
|
||||
@ -18,7 +17,7 @@ export default function PhotoFeedPage({
|
||||
<PhotosLarge {...{ photos }} />
|
||||
{photosCount > photos.length &&
|
||||
<PhotosLargeInfinite
|
||||
initialOffset={INFINITE_SCROLL_FEED_INITIAL}
|
||||
initialOffset={photos.length}
|
||||
itemsPerPage={INFINITE_SCROLL_FEED_MULTIPLE}
|
||||
/>}
|
||||
</div>
|
||||
|
||||
@ -8,7 +8,7 @@ import AnimateItems from '@/components/AnimateItems';
|
||||
import { GRID_ASPECT_RATIO } from '@/app/config';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import SelectTileOverlay from '@/components/SelectTileOverlay';
|
||||
import { JSX } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export default function PhotoGrid({
|
||||
photos,
|
||||
@ -38,7 +38,7 @@ export default function PhotoGrid({
|
||||
canStart?: boolean
|
||||
animateOnFirstLoadOnly?: boolean
|
||||
staggerOnFirstLoadOnly?: boolean
|
||||
additionalTile?: JSX.Element
|
||||
additionalTile?: ReactNode
|
||||
small?: boolean
|
||||
canSelect?: boolean
|
||||
onLastPhotoVisible?: () => void
|
||||
@ -113,7 +113,7 @@ export default function PhotoGrid({
|
||||
)}
|
||||
/>}
|
||||
</div>;
|
||||
}).concat(additionalTile ?? [])}
|
||||
}).concat(additionalTile ? <>{additionalTile}</> : [])}
|
||||
itemKeys={photos.map(photo => photo.id)
|
||||
.concat(additionalTile ? ['more'] : [])}
|
||||
/>
|
||||
|
||||
@ -5,7 +5,7 @@ import PhotoGrid from './PhotoGrid';
|
||||
import PhotoGridInfinite from './PhotoGridInfinite';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import AnimateItems from '@/components/AnimateItems';
|
||||
import { JSX, ComponentProps, useCallback, useState } from 'react';
|
||||
import { ComponentProps, useCallback, useState, ReactNode } from 'react';
|
||||
|
||||
export default function PhotoGridContainer({
|
||||
cacheKey,
|
||||
@ -23,8 +23,8 @@ export default function PhotoGridContainer({
|
||||
}: {
|
||||
cacheKey: string
|
||||
count: number
|
||||
header?: JSX.Element
|
||||
sidebar?: JSX.Element
|
||||
header?: ReactNode
|
||||
sidebar?: ReactNode
|
||||
} & ComponentProps<typeof PhotoGrid>) {
|
||||
const [
|
||||
shouldAnimateDynamicItems,
|
||||
@ -34,8 +34,6 @@ export default function PhotoGridContainer({
|
||||
const onAnimationComplete = useCallback(() =>
|
||||
setShouldAnimateDynamicItems(true), []);
|
||||
|
||||
const initialOffset = photos.length;
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className={clsx(
|
||||
@ -59,10 +57,10 @@ export default function PhotoGridContainer({
|
||||
onAnimationComplete,
|
||||
canSelect,
|
||||
}} />
|
||||
{count > initialOffset &&
|
||||
{count > photos.length &&
|
||||
<PhotoGridInfinite {...{
|
||||
cacheKey,
|
||||
initialOffset,
|
||||
initialOffset: photos.length,
|
||||
canStart: shouldAnimateDynamicItems,
|
||||
tag,
|
||||
camera,
|
||||
|
||||
@ -356,7 +356,7 @@ export default function PhotoLarge({
|
||||
'text-medium',
|
||||
'border-medium rounded-md',
|
||||
'px-[4px] py-[2.5px] my-[-3px]',
|
||||
'translate-y-[2px]',
|
||||
'translate-y-[1.5px]',
|
||||
'hover:bg-dim active:bg-main',
|
||||
)}>
|
||||
{shouldShowRecipe
|
||||
|
||||
@ -69,6 +69,7 @@ const createPhotosTable = () =>
|
||||
const safelyQueryPhotos = async <T>(
|
||||
callback: () => Promise<T>,
|
||||
debugMessage: string,
|
||||
options?: GetPhotosOptions,
|
||||
): Promise<T> => {
|
||||
let result: T;
|
||||
|
||||
@ -122,7 +123,10 @@ const safelyQueryPhotos = async <T>(
|
||||
if (ADMIN_SQL_DEBUG_ENABLED && debugMessage) {
|
||||
const time =
|
||||
(((new Date()).getTime() - start.getTime()) / 1000).toFixed(2);
|
||||
console.log(`Executing sql query: ${debugMessage} (${time} seconds)`);
|
||||
console.log(
|
||||
`Executing sql query: ${debugMessage} (${time} seconds)`,
|
||||
options ? { options } : undefined,
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -410,7 +414,11 @@ export const getPhotos = async (options: GetPhotosOptions = {}) =>
|
||||
|
||||
return query(sql.join(' '), values)
|
||||
.then(({ rows }) => rows.map(parsePhotoFromDb));
|
||||
}, 'getPhotos');
|
||||
},
|
||||
'getPhotos',
|
||||
// Seemingly necessary to pass `options` for expected cache behavior
|
||||
options,
|
||||
);
|
||||
|
||||
export const getPhotosNearId = async (
|
||||
photoId: string,
|
||||
|
||||
@ -4,7 +4,7 @@ import Modal from '@/components/Modal';
|
||||
import { TbPhotoShare } from 'react-icons/tb';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { BiCopy } from 'react-icons/bi';
|
||||
import { JSX, ReactNode, useEffect } from 'react';
|
||||
import { ReactNode, useEffect } from 'react';
|
||||
import { shortenUrl } from '@/utility/url';
|
||||
import { toastSuccess } from '@/toast';
|
||||
import { PiXLogo } from 'react-icons/pi';
|
||||
@ -35,7 +35,7 @@ export default function ShareModal({
|
||||
}, [setShouldRespondToKeyboardCommands]);
|
||||
|
||||
const renderIcon = (
|
||||
icon: JSX.Element,
|
||||
icon: ReactNode,
|
||||
action: () => void,
|
||||
embedded?: boolean,
|
||||
) =>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user