mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
perf: Lazy loading for links in topic sections (#127)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import React, { useRef } from "react"
|
||||
import { TopicDetailHeader } from "./Header"
|
||||
import { TopicSections } from "./partials/topic-sections"
|
||||
import { useLinkNavigation } from "./use-link-navigation"
|
||||
@@ -16,8 +16,10 @@ export const openPopoverForIdAtom = atom<string | null>(null)
|
||||
|
||||
export function TopicDetailRoute({ topicName }: TopicDetailRouteProps) {
|
||||
const { me } = useAccount({ root: { personalLinks: [] } })
|
||||
const { topic, allLinks } = useTopicData(topicName)
|
||||
const { activeIndex, setActiveIndex, containerRef, linkRefs } = useLinkNavigation(allLinks)
|
||||
const { topic } = useTopicData(topicName, me)
|
||||
// const { activeIndex, setActiveIndex, containerRef, linkRefs } = useLinkNavigation(allLinks)
|
||||
const linksRefDummy = useRef<(HTMLLIElement | null)[]>([])
|
||||
const containerRefDummy = useRef<HTMLDivElement>(null)
|
||||
|
||||
if (!topic || !me) {
|
||||
return null
|
||||
@@ -29,10 +31,10 @@ export function TopicDetailRoute({ topicName }: TopicDetailRouteProps) {
|
||||
<TopicSections
|
||||
topic={topic}
|
||||
sections={topic.latestGlobalGuide?.sections}
|
||||
activeIndex={activeIndex}
|
||||
setActiveIndex={setActiveIndex}
|
||||
linkRefs={linkRefs}
|
||||
containerRef={containerRef}
|
||||
activeIndex={0}
|
||||
setActiveIndex={() => {}}
|
||||
linkRefs={linksRefDummy}
|
||||
containerRef={containerRefDummy}
|
||||
me={me}
|
||||
personalLinks={me.root.personalLinks}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from "react"
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { LinkItem } from "./link-item"
|
||||
import { LaAccount, PersonalLinkLists, Section as SectionSchema, Topic, UserRoot } from "@/lib/schema"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import { Loader2 } from "lucide-react"
|
||||
|
||||
interface SectionProps {
|
||||
topic: Topic
|
||||
@@ -27,6 +29,12 @@ export function Section({
|
||||
me,
|
||||
personalLinks
|
||||
}: SectionProps) {
|
||||
const [nLinksToLoad, setNLinksToLoad] = useState(10);
|
||||
|
||||
const linksToLoad = useMemo(() => {
|
||||
return section.links?.slice(0, nLinksToLoad)
|
||||
}, [section.links, nLinksToLoad])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center gap-4 px-6 py-2 max-lg:px-4">
|
||||
@@ -35,9 +43,9 @@ export function Section({
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-px py-2">
|
||||
{section.links?.map(
|
||||
{linksToLoad?.map(
|
||||
(link, index) =>
|
||||
link?.url && (
|
||||
link?.url ? (
|
||||
<LinkItem
|
||||
key={index}
|
||||
topic={topic}
|
||||
@@ -51,9 +59,52 @@ export function Section({
|
||||
me={me}
|
||||
personalLinks={personalLinks}
|
||||
/>
|
||||
) : (
|
||||
<Skeleton key={index} className="h-14 xl:h-11 w-full" />
|
||||
)
|
||||
)}
|
||||
{section.links?.length && section.links?.length > nLinksToLoad && (
|
||||
<LoadMoreSpinner onLoadMore={() => setNLinksToLoad(n => n + 10)} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const LoadMoreSpinner = ({ onLoadMore }: { onLoadMore: () => void }) => {
|
||||
const spinnerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const handleIntersection = useCallback(
|
||||
(entries: IntersectionObserverEntry[]) => {
|
||||
const [entry] = entries
|
||||
if (entry.isIntersecting) {
|
||||
onLoadMore()
|
||||
}
|
||||
},
|
||||
[onLoadMore]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(handleIntersection, {
|
||||
root: null,
|
||||
rootMargin: "0px",
|
||||
threshold: 1.0,
|
||||
})
|
||||
|
||||
if (spinnerRef.current) {
|
||||
observer.observe(spinnerRef.current)
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (spinnerRef.current) {
|
||||
observer.unobserve(spinnerRef.current)
|
||||
}
|
||||
}
|
||||
}, [handleIntersection])
|
||||
|
||||
return (
|
||||
<div ref={spinnerRef} className="flex justify-center py-4">
|
||||
<Loader2 className="h-6 w-6 animate-spin" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user