Home
Blocks

Lazy Block

11/11/2025, 4:59:34 PM modified by Marvin

A 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

PropTypeDefaultDescription
childrenReact.ReactNode内容在 LazyBlock 进入视口时渲染。
classNamestring追加到容器上的自定义类名。
optionsIntersectionObserverInit{ root: null, rootMargin: "-20px", threshold: 0 }传递给 IntersectionObserver 的配置。
seoReactNode未进入视口时用于 SEO 的备用内容,会占位但保持透明。
minHeightstring"1px"在真实内容渲染前用于占位的最小高度。

Git Commit History(1 commits)

feat: 新增LazyBlock组件

Marvin
11月11日 16:59
d74a686a