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 View — style, children, etc.
| Prop | Type | Default | Description |
|---|---|---|---|
style | ViewStyle | {} | Layout and appearance (same as View) |
children | ReactNode | — | The 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.