🚧 VeloxKit is pre-release software. APIs may change before v1.0. Get started →
Documentation
Components
RepaintBoundary

RepaintBoundary Stable WINMACLNX

A render-layer boundary that caches its subtree's GPU scene fragment. When none of the children inside the boundary are dirty, VeloxKit replays the cached fragment directly — skipping the entire subtree traversal and all Vello draw calls.

Inspired by Flutter's RepaintBoundary and React Native's shouldRasterizeIOS.

Import

import { RepaintBoundary } from 'veloxkit'

Basic usage

Wrap any subtree that renders infrequently relative to the rest of your UI:

<RepaintBoundary>
  <Sidebar />
</RepaintBoundary>
<RepaintBoundary>
  <NavigationBar />
</RepaintBoundary>

When to use it

Use RepaintBoundary when a subtree:

  • Changes rarely — sidebars, navbars, static header/footer, complex static cards
  • Is expensive to render — many nested views, gradients, or text nodes
  • Sits next to a high-frequency updater — e.g. a data panel next to an animated chart

The boundary has no effect on layout — it behaves identically to View for sizing and positioning.

RepaintBoundary saves GPU compute time (Vello scene building), not memory. The cache is a Vello scene fragment stored in CPU memory, not a GPU texture.

When NOT to use it

Avoid wrapping subtrees that update every frame (animations, live counters, video frames). The boundary adds a small overhead on dirty frames to capture the new scene fragment. If every frame is dirty, that overhead is pure cost with no benefit.

// ❌ No benefit — content changes every frame
<RepaintBoundary>
  <AnimatedChart data={liveData} />
</RepaintBoundary>
 
// ✅ Good — static shell around a dynamic content area
<View style={{ flex: 1, flexDirection: 'row' }}>
  <RepaintBoundary>
    <Sidebar />        {/* rarely changes */}
  </RepaintBoundary>
  <AnimatedChart data={liveData} />   {/* updates freely */}
</View>

Props

RepaintBoundary accepts all the same props as Viewstyle, children, etc.

PropTypeDefaultDescription
styleViewStyle{}Layout and appearance (same as View)
childrenReactNodeThe subtree to cache

Performance notes

  • On clean frames (no descendants dirty): O(1) replay — the cached scene fragment is appended directly, skipping all child traversal
  • On dirty frames (any descendant changed): the subtree re-renders normally and the new fragment is captured for future frames
  • The cache is cleared on HMR reload and window recreate

Real-world example

A notes app with a static sidebar and a live editor:

export default function App() {
  const [note, setNote] = useState(notes[0])
 
  return (
    <View style={{ flex: 1, flexDirection: 'row' }}>
 
      {/* Sidebar: only re-renders when note selection changes */}
      <RepaintBoundary>
        <NoteList
          notes={notes}
          selected={note.id}
          onSelect={setNote}
        />
      </RepaintBoundary>
 
      {/* Editor: re-renders on every keystroke */}
      <NoteEditor note={note} onChange={updateNote} />
 
    </View>
  )
}

In this layout, typing in the editor only re-renders NoteEditor. The NoteList subtree is skipped entirely — its cached fragment is replayed as-is.