DeferredView
Defer mounting of child components until they become visible in the viewport. Use it to lazy-load heavy components, defer API calls, delay image buffering, or skip rendering content hidden in inactive tabs.
Basic Usage
Scroll to reveal
Scroll down within this container to see components mount only when they enter the viewport. Each card logs when it was mounted.
import { DeferredView } from 'fluxo-ui';
<DeferredView>
<ExpensiveComponent />
</DeferredView>
<DeferredView>
<AnotherExpensiveComponent />
</DeferredView>Custom Placeholder
Custom placeholder
Use the placeholder prop to show a shimmer skeleton or any custom loading UI while the real content is deferred.
import { DeferredView, ShimmerDiv } from 'fluxo-ui';
const placeholder = (
<div className="space-y-3 p-6">
<ShimmerDiv style={{ height: 20, width: '40%', borderRadius: 4 }} />
<ShimmerDiv style={{ height: 14, width: '80%', borderRadius: 4 }} />
</div>
);
<DeferredView placeholder={placeholder}>
<ExpensiveComponent />
</DeferredView>Keep Mounted
keepMounted vs unmount on leave
With keepMounted (default), once a component mounts it stays mounted even when scrolled out of view. Set keepMounted={false} to unmount when leaving the viewport — the counter resets each time.
// Default: stays mounted once visible
<DeferredView keepMounted>
<StatefulComponent />
</DeferredView>
// Unmounts when scrolled out of view
<DeferredView keepMounted={false}>
<StatefulComponent />
</DeferredView>Root Margin
Root margin for preloading
Use rootMargin to start loading content before it enters the viewport. With rootMargin="200px", components begin mounting 200px before they scroll into view.
// Preload 200px before entering viewport
<DeferredView rootMargin="200px">
<HeavyComponent />
</DeferredView>
// Preload 50% of viewport height ahead
<DeferredView rootMargin="50%">
<HeavyComponent />
</DeferredView>Lazy Image Gallery
Lazy image gallery
Images are not fetched until their container enters the viewport. This is ideal for long pages with many images.
import { DeferredView, ShimmerDiv } from 'fluxo-ui';
const placeholder = <ShimmerDiv style={{ height: 185, width: '100%' }} />;
{images.map((url) => (
<DeferredView key={url} placeholder={placeholder} rootMargin="50px">
<img src={url} alt="Lazy loaded" />
</DeferredView>
))}API Reference
childrenReactNodeContent to render once the component enters the viewport.
childrenReactNodeContent to render once the component enters the viewport.
placeholderReactNode"empty div"Content to show while the children are deferred. Use a shimmer skeleton, spinner, or any custom placeholder.
placeholderReactNode"empty div"Content to show while the children are deferred. Use a shimmer skeleton, spinner, or any custom placeholder.
rootMarginstring""0px""Margin around the root (viewport) for the IntersectionObserver. Use positive values to preload content before it enters the viewport (e.g. "200px").
rootMarginstring""0px""Margin around the root (viewport) for the IntersectionObserver. Use positive values to preload content before it enters the viewport (e.g. "200px").
thresholdnumber"0"Percentage of the element that must be visible before mounting (0 to 1). 0 means any pixel visible triggers mount.
thresholdnumber"0"Percentage of the element that must be visible before mounting (0 to 1). 0 means any pixel visible triggers mount.
keepMountedboolean"true"When true, children stay mounted after first visibility. When false, children unmount when scrolled out of view.
keepMountedboolean"true"When true, children stay mounted after first visibility. When false, children unmount when scrolled out of view.
classNamestringAdditional CSS classes applied to the wrapper element.
classNamestringAdditional CSS classes applied to the wrapper element.
styleCSSPropertiesInline styles applied to the wrapper element.
styleCSSPropertiesInline styles applied to the wrapper element.
Features
Viewport Aware
Uses IntersectionObserver to detect when children enter the viewport — works inside scrollable containers, tab panels, and page scroll
Zero Dependencies
Built entirely on the native IntersectionObserver API — no external libraries needed
Preloading
Configure rootMargin to begin loading content before it enters the viewport for a seamless experience
Keep Mounted
Choose whether components stay mounted after first render or unmount when scrolled away to reclaim memory
Custom Placeholders
Show shimmer skeletons, spinners, or any React node as a placeholder while content is deferred
Performance
Defer API calls, image loading, and heavy renders to reduce initial page load time and memory usage