From 0a68b0b07d0f70aee08decc65244bc9fe1f7135f Mon Sep 17 00:00:00 2001 From: Lee Hansel Solevilla <13744167+sshanzel@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:31:25 +0800 Subject: [PATCH] refactor: avoid unnecessary calls and properties in squads directory page (#3609) --- .../HorizontalScroll/HorizontalScroll.tsx | 26 +++++--- .../cards/squad/SquadsDirectoryFeed.tsx | 18 ++++-- packages/shared/src/graphql/fragments.ts | 59 ++++++++++--------- .../shared/src/hooks/source/useSources.ts | 3 + packages/webapp/pages/squads/index.tsx | 7 --- 5 files changed, 65 insertions(+), 48 deletions(-) diff --git a/packages/shared/src/components/HorizontalScroll/HorizontalScroll.tsx b/packages/shared/src/components/HorizontalScroll/HorizontalScroll.tsx index 4f6e780308..a67188da6a 100644 --- a/packages/shared/src/components/HorizontalScroll/HorizontalScroll.tsx +++ b/packages/shared/src/components/HorizontalScroll/HorizontalScroll.tsx @@ -1,4 +1,10 @@ -import React, { ReactElement, ReactNode, useId } from 'react'; +import React, { + forwardRef, + MutableRefObject, + ReactElement, + ReactNode, + useId, +} from 'react'; import classNames from 'classnames'; import { UseHorizontalScrollHeaderProps, @@ -16,18 +22,20 @@ interface HorizontalScrollProps { scrollProps: UseHorizontalScrollHeaderProps; } -export default function HorizontalScroll({ - children, - className, - scrollProps, -}: HorizontalScrollProps): ReactElement { +function HorizontalScrollComponent( + { children, className, scrollProps }: HorizontalScrollProps, + propRef: MutableRefObject, +): ReactElement { const { ref, Header } = useHorizontalScrollHeader(scrollProps); const id = useId(); const titleId = `horizontal-scroll-title-${id}`; return ( -
+
); } + +const HorizontalScroll = forwardRef(HorizontalScrollComponent); + +export default HorizontalScroll; diff --git a/packages/shared/src/components/cards/squad/SquadsDirectoryFeed.tsx b/packages/shared/src/components/cards/squad/SquadsDirectoryFeed.tsx index 1011a916bb..92dc40fceb 100644 --- a/packages/shared/src/components/cards/squad/SquadsDirectoryFeed.tsx +++ b/packages/shared/src/components/cards/squad/SquadsDirectoryFeed.tsx @@ -1,4 +1,5 @@ import React, { ReactElement, ReactNode } from 'react'; +import { useInView } from 'react-intersection-observer'; import { Squad } from '../../../graphql/sources'; import { SourcesQueryProps, @@ -41,20 +42,24 @@ export function SquadsDirectoryFeed({ className, children, }: SquadHorizontalListProps): ReactElement { - const { result } = useSources({ query }); - const { isInitialLoading } = result; + const { ref, inView } = useInView({ + triggerOnce: true, + }); + const { result } = useSources({ query, isEnabled: inView }); + const { isFetched } = result; const isMobile = useViewSize(ViewSize.MobileL); + const isLoading = !isFetched || (!inView && !result.data); const flatSources = result.data?.pages.flatMap((page) => page.sources.edges) ?? []; - if (flatSources.length === 0 && !isInitialLoading) { + if (flatSources.length === 0 && isFetched) { return null; } if (isMobile) { return ( -
+
{children}
{title} @@ -71,13 +76,14 @@ export function SquadsDirectoryFeed({ {flatSources?.map(({ node }) => ( ))} - {isInitialLoading && } + {isLoading && }
); } return ( @@ -89,7 +95,7 @@ export function SquadsDirectoryFeed({ ), )} - {isInitialLoading && } + {isLoading && } ); } diff --git a/packages/shared/src/graphql/fragments.ts b/packages/shared/src/graphql/fragments.ts index c8b4e599fe..3ea8e124c7 100644 --- a/packages/shared/src/graphql/fragments.ts +++ b/packages/shared/src/graphql/fragments.ts @@ -76,6 +76,30 @@ export const SOURCE_SHORT_INFO_FRAGMENT = gql` } `; +export const PRIVILEGED_MEMBERS_FRAGMENT = gql` + fragment PrivilegedMembers on Source { + privilegedMembers { + user { + id + name + image + permalink + username + bio + reputation + companies { + name + image + } + contentPreference { + status + } + } + role + } + } +`; + // this query should use UserShortInfo fragment once the createdAt issue is fixed. // for the mean time, we should not include the said property on privilegedMembers. export const SOURCE_BASE_FRAGMENT = gql` @@ -90,16 +114,6 @@ export const SOURCE_BASE_FRAGMENT = gql` description image membersCount - privilegedMembers { - user { - id - } - role - } - category { - id - title - } currentMember { ...CurrentMember } @@ -120,27 +134,14 @@ export const SQUAD_BASE_FRAGMENT = ` totalViews totalUpvotes } - privilegedMembers { - user { - id - name - image - permalink - username - bio - reputation - companies { - name - image - } - contentPreference { - status - } - } - role + category { + id + title } + ...PrivilegedMembers } ${SOURCE_BASE_FRAGMENT} + ${PRIVILEGED_MEMBERS_FRAGMENT} `; export const SHARED_POST_INFO_FRAGMENT = gql` @@ -175,6 +176,7 @@ export const SHARED_POST_INFO_FRAGMENT = gql` tags source { ...SourceBaseInfo + ...PrivilegedMembers } downvoted flags { @@ -189,6 +191,7 @@ export const SHARED_POST_INFO_FRAGMENT = gql` slug domain } + ${PRIVILEGED_MEMBERS_FRAGMENT} ${SOURCE_BASE_FRAGMENT} ${USER_AUTHOR_FRAGMENT} `; diff --git a/packages/shared/src/hooks/source/useSources.ts b/packages/shared/src/hooks/source/useSources.ts index 4d52ed48f1..b2775c866a 100644 --- a/packages/shared/src/hooks/source/useSources.ts +++ b/packages/shared/src/hooks/source/useSources.ts @@ -25,10 +25,12 @@ export interface SourcesQueryProps { interface UseSourcesProps { query?: SourcesQueryProps; + isEnabled?: boolean; } export const useSources = ({ query = {}, + isEnabled = true, }: UseSourcesProps = {}): UseSources => { const { featured, @@ -60,6 +62,7 @@ export const useSources = ({ lastPage?.sources?.pageInfo?.hasNextPage && lastPage?.sources?.pageInfo?.endCursor, staleTime: StaleTime.Default, + enabled: isEnabled, }, ); diff --git a/packages/webapp/pages/squads/index.tsx b/packages/webapp/pages/squads/index.tsx index 87df40a578..60cb767e2c 100644 --- a/packages/webapp/pages/squads/index.tsx +++ b/packages/webapp/pages/squads/index.tsx @@ -1,14 +1,7 @@ import React, { ReactElement } from 'react'; -import { InfiniteData } from '@tanstack/react-query'; import { GetServerSidePropsResult } from 'next'; -import { Squad } from '@dailydotdev/shared/src/graphql/sources'; -import { SourcesQueryData } from '@dailydotdev/shared/src/hooks/source/useSources'; import { squadCategoriesPaths } from '@dailydotdev/shared/src/lib/constants'; -export type Props = { - initialData?: InfiniteData>; -}; - const SquadsPage = (): ReactElement => { return <>; };