React Native’s JavaScript bridge was a well-known performance bottleneck for years. Under heavy UI pressure (fast scrolling, frequent re-renders), teams could hit dropped frames and visible “blank” rendering while work moved across threads and through serialization.
Meta’s New Architecture (JSI, Fabric, TurboModules) changes that baseline. By replacing the legacy bridge with direct, C++-backed interop and a new renderer, React Native closes much of the historical performance gap for many real-world apps.
Valdi takes a more radical approach. Built and battle-tested internally at Snapchat, Valdi compiles TypeScript into native iOS and Android UI primitives rather than shipping a JavaScript runtime and reconciling a virtual tree at runtime. For teams balancing performance targets against hiring constraints and release velocity, the question becomes practical: if you can compile to native without React’s runtime overhead, is the performance upside worth the ecosystem risk?
This article compares React Native and Valdi across four trade-offs:
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
The architectural choice you make here determines your maintenance burden for years. React Native’s New Architecture removes the legacy bridge but introduces a more layered mental model (JSI, Fabric, TurboModules) that can surface as multi-language debugging across JavaScript, C++, and platform-native code. Valdi eliminates several runtime layers by compiling TypeScript ahead of time, but shifts complexity into build tooling, compilation artifacts, and polyglot modules for platform integration.
React Native’s legacy model serialized UI updates through a bridge between JavaScript and native threads. The New Architecture replaces that with:
The trade-off is that performance improvements often arrive with deeper system complexity. When issues occur, investigation can span JavaScript code, C++ interop boundaries, and native implementations.
Valdi approaches the same problem by moving more work to build time. TypeScript components compile into .valdimodule artifacts that encode layout instructions and behavior bindings. At runtime, the Valdi engine reads compiled modules and renders native views directly. JSX emits render operations as side effects during onRender(), and components update explicitly without relying on parent re-renders:

Here’s what that difference looks like at the component level:
// React Native - Virtual DOM reconciliation
function FeedItem({ title, image, onLike }) {
const [liked, setLiked] = useState(false);
return (
<View style={styles.container}>
<Image source={{ uri: image }} style={styles.image} />
<Text style={styles.title}>{title}</Text>
<TouchableOpacity onPress={() => setLiked(!liked)}>
<Text>{liked ? '❤️' : '🤍'}</Text>
</TouchableOpacity>
</View>
);
}
// Valdi - Class-based components with onRender lifecycle
import { Component } from 'valdi_core/src/Component';
interface FeedItemViewModel {
title: string;
image: string;
}
class FeedItem extends Component<FeedItemViewModel> {
private liked = false;
onRender() {
<view backgroundColor="white" padding={16}>
<image source={this.viewModel.image} height={200} />
<label value={this.viewModel.title} fontSize={18} />
<view onTap={() => {
this.liked = !this.liked;
this.markNeedsRender();
}}>
<label value={this.liked ? '❤️' : '🤍'} />
</view>
</view>;
}
}
React Native reconciles virtual trees to determine what changed. When debugging performance issues, you often trace through reconciliation, renderer behavior, and (in some cases) JSI-related boundaries. Valdi’s model is more explicit: JSX emits operations during onRender(), and updates are scheduled by calling markNeedsRender().
That simplicity comes with constraints. React’s virtual tree makes dynamic composition and structural UI changes idiomatic. Valdi’s update model can be easier to reason about for targeted updates, but it can feel less flexible when your UI depends heavily on composition patterns, dynamic lists, and shared abstractions.
In practice, the maintenance decision is usually this: React Native can be more complex internally, but it is backed by years of community debugging, known optimization playbooks, and battle-tested tooling. Valdi can reduce runtime moving parts, but you should expect to hit edge cases earlier and solve more problems without an established ecosystem.
Developer velocity is not just “how fast you can code.” It is how rarely you get blocked by tooling, docs, and missing libraries. React Native’s advantage is that most problems you hit have already been solved publicly. Valdi’s advantage is tighter control over runtime behavior and feedback loops, but the framework’s youth means gaps show up as engineering work rather than a package install.
React Native’s happy path is mature: npx react-native init typically gets teams to first render quickly. Valdi’s early-adopter experience can include dependency mismatches, build tool errors, and project constraints that reflect its Snapchat-internal origins (for example, naming and path assumptions). The practical consequence is that your “time to first render” may involve debugging build plumbing before you touch product code.
React Native standardizes on functional components and Hooks. Valdi uses class-based components with explicit lifecycle methods, which appears to be a deliberate design decision for predictable render behavior:
// React Native - Functional with Hooks
function ProductCard({ product }) {
const [quantity, setQuantity] = useState(1);
const [inCart, setInCart] = useState(false);
return (
<View style={styles.card}>
<Image source={{ uri: product.image }} />
<Text>{product.name}</Text>
<View style={styles.controls}>
<Button title="-" onPress={() => setQuantity(Math.max(1, quantity - 1))} />
<Text>{quantity}</Text>
<Button title="+" onPress={() => setQuantity(quantity + 1)} />
</View>
<TouchableOpacity onPress={() => setInCart(true)}>
<Text>{inCart ? 'Added ✓' : 'Add to Cart'}</Text>
</TouchableOpacity>
</View>
);
}
// Valdi - Class with onRender
import { Component } from 'valdi_core/src/Component';
class ProductCard extends Component<{ product: Product }> {
private quantity = 1;
private inCart = false;
onRender() {
<view padding={16} backgroundColor="white">
<image source={this.viewModel.product.image} height={200} />
<label value={this.viewModel.product.name} fontSize={16} />
<view flexDirection="row">
<view onTap={() => {
this.quantity = Math.max(1, this.quantity - 1);
this.markNeedsRender();
}}>
<label value="-" />
</view>
<label value={this.quantity.toString()} />
<view onTap={() => {
this.quantity++;
this.markNeedsRender();
}}>
<label value="+" />
</view>
</view>
<view onTap={() => {
this.inCart = true;
this.markNeedsRender();
}}>
<label value={this.inCart ? 'Added ✓' : 'Add to Cart'} />
</view>
</view>;
}
}
React’s reconciler supports compositional patterns most frontend teams already rely on (dynamic arrays, shared component abstractions, render props, HOCs). Valdi trades some compositional flexibility for targeted updates. The model is closer to “explicitly re-render what changed” than “reconcile a new tree.”
For hiring, this matters. React Native candidates arrive with broadly transferable React skills. Valdi requires framework-specific training plus, in many cases, deeper comfort with build systems and native integration work.
Both frameworks can be adopted incrementally inside existing native apps. Snapchat’s Valdi history suggests that a piecemeal approach can work. The difference is what happens when you need third-party capabilities. React Native’s package ecosystem is a major force multiplier. Valdi currently implies rebuilding or wrapping integrations as polyglot modules when off-the-shelf solutions are not available.
That ecosystem maturity often becomes the real velocity driver: React Native reduces time-to-solution under deadline pressure. Valdi can deliver strong feedback loops, but teams should plan for more “build it yourself” work early on.
Performance is about user experience, but optimization strategy is about cost. Valdi’s pitch is predictable performance through constraints: fewer runtime layers, fewer cross-thread boundaries, and more work moved to compilation. React Native’s pitch is flexible performance through patterns and tools: you can reach excellent results, but your team has to apply optimizations correctly.
Some early reports and benchmarks attribute strong scroll performance to Valdi’s architecture (including view pooling and its rendering approach). React Native’s New Architecture is also associated with improvements in specific workloads, although results vary by app, device class, and how much code was previously bottlenecked on the bridge.
Valdi emphasizes reuse via pooling strategies, which can reduce churn under heavy scrolling and across screens. React Native’s FlatList virtualizes within a list and offers tuning knobs like windowSize and removeClippedSubviews, but teams often have to profile and tune those settings to avoid memory and jank regressions.
Fabric and related improvements reduce some historical bottlenecks in React Native rendering. Valdi’s model, by design, aims to keep UI work predictable and scoped, with updates scheduled explicitly. In practice, both can achieve smooth performance on modern devices. The difference is how much engineering effort and expertise it takes to maintain that performance as the product grows.
If your product has known UI patterns and strict performance requirements, Valdi’s constraints may be attractive. If your UI is complex and evolving, React Native’s ecosystem and optimization playbooks can be a safer long-term bet.
Choosing a cross-platform framework is a multi-year platform bet. React Native represents distributed risk across a large ecosystem of maintainers, libraries, and production users. Valdi concentrates risk more heavily around Snapchat’s priorities and the pace of third-party adoption.
Long-term maintenance risk also appears differently. React Native teams often manage dependency churn across upgrades, but benefit from community-led fixes and widely documented migration paths. Valdi teams may avoid some classes of runtime issues, but will frequently pay the integration cost themselves via polyglot modules (C++, Swift, Kotlin) when platform APIs or third-party capabilities are required.
| Factor | React Native | Valdi |
|---|---|---|
| Recommended use cases | Greenfield apps; teams prioritizing velocity; products needing rapid iteration | Incremental adoption in native apps; performance-critical features; teams with strong native expertise |
| Performance upside | Meaningful improvements with the New Architecture in bridge-limited workloads; requires optimization discipline | High ceiling via compilation and reduced runtime layers; performance profile tends to be more predictable when UI fits the model |
| Ecosystem maturity | Large ecosystem; established patterns; extensive Q&A and community solutions | Early ecosystem; limited third-party libraries; more reliance on first-party docs and direct support channels |
| Migration cost | Low for new projects; incremental adoption supported in native contexts | Lower for embedding discrete features; higher for full rewrites when you must rebuild tooling and integrations |
| Team skill requirements | JavaScript/TypeScript; React patterns; comfort with profiling and renderer concepts | TypeScript plus framework-specific patterns; build tooling; C++/Swift/Kotlin for polyglot modules |
| Bus factor | Distributed (Meta plus broad community) | More concentrated (Snapchat-driven; dependent on broader community uptake) |
| When adoption creates more risk than value | When performance requirements exceed what your team can sustain with optimization work | Greenfield projects under tight deadlines; teams without native expertise; products that rely heavily on third-party integrations |
Use the table as a filter, not a scorecard. If you cannot afford ecosystem risk, React Native is usually the default. If your feature set is narrow, performance-critical, and you have native depth, Valdi can be a credible bet.
Valdi’s value proposition is clear: native UI performance via compiled TypeScript, with fewer runtime layers and less cross-boundary overhead. For teams embedding cross-platform UI into existing native apps, that architecture can make sense, and Snapchat’s long-term internal usage is meaningful validation.
But React Native’s New Architecture closes many historical performance gaps while preserving what most teams actually buy: ecosystem leverage. Fabric, JSI, and TurboModules improve the runtime story, and the broader community supplies libraries, patterns, and hiring liquidity that a newer framework cannot quickly replicate.
Today, Valdi reads more like a specialized tool for performance-sensitive, well-scoped surfaces than a full React Native replacement. The strategic question is whether its technical advantages can overcome React Native’s ecosystem moat. For most teams, the answer depends less on raw FPS and more on whether you can sustain the integration and maintenance costs that come with being early.

LogRocket's Galileo AI watches sessions for you and and surfaces the technical and usability issues holding back your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.

What trends will define web development in 2026? Check out the eight most important trends of the year, from AI-first development to TypeScript’s takeover.

AI-first debugging augments traditional debugging with log clustering, pattern recognition, and faster root cause analysis. Learn where AI helps, where it fails, and how to use it safely in production.

Container queries let components respond to their own layout context instead of the viewport. This article explores how they work and where they fit alongside media queries.

React Server Components vs Islands Architecture: Learn how each reduces client JavaScript, impacts hydration and interactivity, and which trade-offs matter for production performance.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now