Blocks
Lazy Block
11/11/2025, 4:59:34 PM modified by MarvinA lazy block component that renders its children once it becomes visible in the viewport.
Installation
Loading...
Notice:
Change import path import { useIntersectionObserver } from '~/registry/hooks/use-intersection-observer';
to actual path import { useIntersectionObserver } from '@/hooks/use-intersection-observer';.
Preview
Index Page
Heaven SEO
Bulky SEO
import type { ReactNode } from 'react';import { cn } from '@/lib/cn';import { useIntersectionObserver } from '~/registry/hooks/use-intersection-observer';interface LazyBlockProps { children: React.ReactNode; className?: string; options?: IntersectionObserverInit; seo?: ReactNode; minHeight?: string; // less than the real height of the block}export default function LazyBlock(props: LazyBlockProps) { const { children, className, options = { root: null, rootMargin: `-20px`, threshold: 0 }, seo, minHeight = '1px', } = props; const { ref, isIntersecting } = useIntersectionObserver<HTMLDivElement>(options); return ( <div ref={ref} className={cn('relative', className)} style={{ minHeight }}> {isIntersecting && children} {!isIntersecting && seo && <div className="opacity-0 absolute w-full h-full pointer-events-none">{seo}</div>} </div> );}export default function Heaven() { return <div className="min-h-[100px] bg-red-500">Heaven</div>;}'use client';import dynamic from 'next/dynamic';import LazyBlock from '~/registry/blocks/lazy-block/lazy-block';import { sleep } from '~/registry/utils/common';const Heaven = dynamic( async () => { await sleep(3000); return import('./heaven'); }, { ssr: false, loading: () => 'Heaven Loading...', },);const Bulky = dynamic( async () => { await sleep(3000); return import('./bulky'); }, { ssr: false, loading: () => 'Bulky Loading...', },);export default function Demo() { return ( <div className="max-h-[600px] border overflow-y-scroll"> <div className="h-[600px]"> <h1>Index Page</h1> </div> <LazyBlock minHeight="200px" seo={<h2>Heaven SEO</h2>}> <Heaven /> </LazyBlock> <LazyBlock minHeight="200px" seo={<h2>Bulky SEO</h2>}> <Bulky /> </LazyBlock> </div> );}export default function Bulky() { return <div className="min-h-[100px] bg-blue-500">Bulky</div>;}API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | – | 内容在 LazyBlock 进入视口时渲染。 |
className | string | – | 追加到容器上的自定义类名。 |
options | IntersectionObserverInit | { root: null, rootMargin: "-20px", threshold: 0 } | 传递给 IntersectionObserver 的配置。 |
seo | ReactNode | – | 未进入视口时用于 SEO 的备用内容,会占位但保持透明。 |
minHeight | string | "1px" | 在真实内容渲染前用于占位的最小高度。 |
Git Commit History(1 commits)
feat: 新增LazyBlock组件
Marvin
11月11日 16:59
d74a686a