React Native's New Architecture: Shipping Fabric and JSI to Production
The new React Native architecture is finally stable. We break down Fabric rendering and JSI performance gains with real code and lessons from shipping to production.
React Native's new architecture has moved from experimental to production-ready. If you've been waiting for a practical guide on when and how to adopt Fabric and the JavaScript Interface (JSI) layer, this is it.
For years, React Native worked through a bridge that serialized data between JavaScript and native code. It was functional but slow—especially for complex UIs and frequent native interactions. The new architecture tears down that bridge and replaces it with direct communication. The results are measurable: lower latency, smoother animations, and better memory usage.
At LavaPi, we've guided clients through this transition. The shift isn't trivial, but it's worth it if you're building performance-critical features.
Understanding Fabric: The New Renderer
Fabric is the new rendering engine. Instead of the old system's asynchronous batch processing, Fabric renders synchronously on the native thread. This means fewer frame drops when the UI needs updates.
How Fabric Changes Your Workflow
The good news: most of your React code doesn't change. Fabric handles the heavy lifting behind the scenes.
typescriptimport React, { useState } from 'react'; import { View, Text, Pressable, StyleSheet } from 'react-native'; const FabricComponent = () => { const [count, setCount] = useState(0); return ( <View style={styles.container}> <Text style={styles.text}>Count: {count}</Text> <Pressable style={styles.button} onPress={() => setCount(count + 1)} > <Text>Increment</Text> </Pressable> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center' }, text: { fontSize: 18, marginBottom: 16 }, button: { padding: 10, backgroundColor: '#007AFF', borderRadius: 8 }, }); export default FabricComponent;
This component works identically in both architectures. The difference is internal—Fabric executes the render cycle more efficiently.
Where Fabric shines is animations and rapid state changes. If you're updating a scroll position, gesture-driven UI, or real-time data, you'll notice the improvement immediately.
JSI: Direct Native Access Without the Bridge
JavaScript Interface (JSI) lets you call native code directly without serialization overhead. This is critical for performance-intensive operations: cryptography, audio processing, or complex data transformations.
Writing a JSI Module
Creating a JSI module requires native code, but the JavaScript side is clean:
typescriptimport { NativeModules } from 'react-native'; const CryptoModule = NativeModules.CryptoModule; const hashData = async (input: string): Promise<string> => { return CryptoModule.sha256(input); }; export default hashData;
On the native side (Kotlin), you implement the JSI binding:
kotlinpackage com.example.crypto import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactMethod class CryptoModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName() = "CryptoModule" @ReactMethod fun sha256(input: String, promise: Promise) { val digest = MessageDigest.getInstance("SHA-256") val hash = digest.digest(input.toByteArray()) val hex = hash.joinToString("") { "%02x".format(it) } promise.resolve(hex) } }
The performance gain depends on what you're doing. For I/O-bound operations, you might see 2–4x speedup. For CPU-bound work, the difference can be even more dramatic.
Enabling the New Architecture
Migration isn't automatic. You need to opt in at the project level.
In your
android/gradle.propertiesbashnewArchEnabled=true
For iOS, set the flag in your Podfile:
bashpost_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['RCT_NEW_ARCH_ENABLED'] = 'YES' end end end
Then rebuild and test thoroughly. Incompatible third-party libraries will fail—check your dependencies against the new architecture compatibility matrix before upgrading.
What You Actually Need to Know
Fabric and JSI aren't magic. Use Fabric if you're building a new app or modernizing an existing one—the stability and performance justify the upgrade cycle. Use JSI when you have specific bottlenecks: expensive computations, frequent native calls, or real-time operations.
Start with profiling. Identify where your app is slow, then decide if the new architecture solves it. Skip it if your app runs fine on the old system.
The new architecture is production-ready. The ecosystem is catching up. Build with confidence.
LavaPi Team
Digital Engineering Company