valdi-perf

Diagnose and fix re-render, layout, and threading performance issues in Valdi TypeScript components.

16.4k|541|Updated Nov 6, 2025
One-click install
npx skills add https://github.com/Snapchat/Valdi --skill valdi-perf
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: valdi-perf
Source: https://github.com/Snapchat/Valdi/tree/main/ai-skills/skills/valdi-perf
Command: npx skills add https://github.com/Snapchat/Valdi --skill valdi-perf

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Valdi apps re-render child components whenever a viewModel reference changes, so object literals, inline callbacks, and per-render allocations created inside onRender() cause unnecessary re-renders, slow first paint, and janky scrolling. This Skill provides concrete patterns to find and fix those reference-identity, rendering, and threading problems.

Core Features & Use Cases

  • Reference Stability Patterns: Keep viewModels, callbacks, render props, and Style objects stable across renders using class arrow functions, pre-computed viewModels in onViewModelUpdate, createReusableCallback, remember, and module-level Style instances.
  • Rendering & List Optimization: Choose <layout> over <view> for virtual containers, use stable keys in lists, batch setState calls, and enable native sticky headers to eliminate scroll lag.
  • Startup & Threading Offload: Defer work with Lazy, Provider, dynamic import(), lazyImport, setTimeout(0) subscription deferral, cacheObservable, and Worker Services with MessageChannel for heavy computation.
  • Use Case: A Valdi screen stutters when scrolling a list and re-renders every row on each state change. Apply stable keys, a cached row viewModel, a class-arrow renderItem, and cacheObservable on the data stream to eliminate the redundant renders.

Quick Start

Ask the assistant to review your Valdi component's onRender() and state updates for performance problems using the valdi-perf patterns.

Frequently Asked Questions about valdi-perf

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I stop Valdi components from re-rendering unnecessarily?

Valdi re-renders a child whenever its viewModel reference changes, so avoid creating object, array, or function literals inside onRender(). Hoist constants to class properties, pre-compute derived viewModels in onViewModelUpdate, and use class arrow functions for callbacks.

What is the difference between <layout> and <view> in Valdi?

<view> allocates a native platform view, while <layout> is a virtual node that participates in flexbox layout without creating a native view. Use <layout> for spacers and structural wrappers, and <view> only when you need visual or interactive properties like onTap or backgroundColor.

When should I use remember versus createReusableCallback in Valdi?

remember caches a computed value across renders and recomputes only when its key dependencies change. createReusableCallback stabilizes a function's identity so Valdi's diffing engine does not treat it as a prop change. Use remember for values and createReusableCallback for inline closures.

Why does subscribing to observables in onCreate slow down first paint?

Each .subscribe() on a BridgeObservable creates the native bridge and runs the initial value flow synchronously, delaying first paint, and multiple subscriptions compound the delay. Defer non-critical subscriptions with setTimeout(0) so they run on the next tick after the initial render.

When should I move work to a Valdi Worker Service?

Use a Worker Service for expensive synchronous TypeScript work like parsing or transforms when the caller can tolerate an asynchronous promise-based API. Arguments are deep-copied across the thread boundary, idle workers are torn down, and synchronous return values are not supported, so cheap or render-path work should stay on the host thread.

How do I fix multiple setState calls causing extra renders in Valdi?

setState runs synchronously with no frame-level batching, so N calls produce N renders. Merge related updates into a single setState call, and for chatty observables apply distinctUntilChanged or debounceTime upstream of the subscribe call.