{"id":4915,"date":"2026-10-25T23:51:34","date_gmt":"2026-10-25T18:21:34","guid":{"rendered":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/"},"modified":"2026-10-25T23:51:34","modified_gmt":"2026-10-25T18:21:34","slug":"react-native-guide-build-high-performance-mobile-apps-3","status":"publish","type":"post","link":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/","title":{"rendered":"React Native Guide: Build High-Performance Mobile Apps"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6adfd922b42c5\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6adfd922b42c5\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#React_Native_The_Bridge_is_Out_and_Your_App_is_OOM-Killed\" >React Native: The Bridge is Out and Your App is OOM-Killed<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#The_Documentation_Lie_Its_Not_Just_JavaScript\" >The Documentation Lie: It\u2019s Not Just JavaScript<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#The_Architecture_The_Bridge_vs_JSI\" >The Architecture: The Bridge vs. JSI<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#Hermes_The_Engine_You_Cant_Ignore\" >Hermes: The Engine You Can&#8217;t Ignore<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#The_Native_Module_Trap\" >The Native Module Trap<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#State_Management_Redux_is_a_Sledgehammer\" >State Management: Redux is a Sledgehammer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#The_Build_System_Where_Dreams_Go_to_Die\" >The Build System: Where Dreams Go to Die<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#The_%E2%80%9CGotcha%E2%80%9D_The_Keyboard_and_the_Notch\" >The &#8220;Gotcha&#8221;: The Keyboard and the Notch<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#Performance_Profiling_Beyond_consolelog\" >Performance Profiling: Beyond console.log<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#The_Upgrade_Path_A_Tale_of_Woe\" >The Upgrade Path: A Tale of Woe<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#Is_It_Worth_It\" >Is It Worth It?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#Related_Articles\" >Related Articles<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"React_Native_The_Bridge_is_Out_and_Your_App_is_OOM-Killed\"><\/span>React Native: The Bridge is Out and Your App is OOM-Killed<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>It was 3:00 AM on a Tuesday in 2021. I was the lead SRE for a fintech startup that had just launched a high-yield savings feature. We built the mobile app in <strong>react native<\/strong> because the &#8220;velocity&#8221; was supposed to be unmatched. We hit the top of Hacker News. Then, the alerts started firing. Our Sentry dashboard looked like a crime scene. Every single user on a mid-range Android device\u2014think Samsung Galaxy A series\u2014was experiencing a hard crash within 45 seconds of opening the app. The logs showed a consistent <code>java.lang.OutOfMemoryError<\/code>. <\/p>\n<p>We had built a complex, beautiful dashboard with real-time SVG charts and a massive <code>FlatList<\/code> of transactions. The &#8220;Bridge&#8221;\u2014that glorious architectural bottleneck that passes JSON messages between JavaScript and Native\u2014was backed up like the 405 at rush hour. We were pushing 60 updates per second over the bridge to update a progress bar, and the serializing\/deserializing overhead was eating the heap alive. I spent the next 18 hours rewriting the transaction list to use a windowing logic that the documentation barely mentioned, while the CTO breathed down my neck. We didn&#8217;t &#8220;unlock&#8221; anything that day; we just barely survived the &#8220;write once, debug everywhere&#8221; reality of cross-platform development.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_Documentation_Lie_Its_Not_Just_JavaScript\"><\/span>The Documentation Lie: It\u2019s Not Just JavaScript<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you read the official <strong>react native<\/strong> docs, they make it sound like you\u2019re just writing React for phones. That is a dangerous oversimplification. In a real production environment, you are managing three distinct runtime environments simultaneously: the JavaScript VM (Hermes), the Android Runtime (ART\/Dalvik), and the iOS Runtime (Objective-C\/Swift). If you don&#8217;t understand how these three interact, you aren&#8217;t building an app; you&#8217;re building a ticking time bomb.<\/p>\n<p>The documentation loves to talk about &#8220;Hot Reloading.&#8221; It rarely talks about the <code>AppDelegate.mm<\/code> or the <code>MainApplication.java<\/code>. It ignores the fact that when you need to integrate a specific SDK\u2014like a high-security biometric scanner or a custom Bluetooth LE protocol\u2014you will be writing C++ or Java. You cannot escape the native layer. Most teams fail because they hire five JS developers and zero engineers who know what a <code>Podfile.lock<\/code> actually does. They end up in &#8220;dependency hell&#8221; where <code>react-native-reanimated<\/code> version X requires <code>react-native-gesture-handler<\/code> version Y, but only if you&#8217;re using Gradle 7.4. It\u2019s a house of cards.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_Architecture_The_Bridge_vs_JSI\"><\/span>The Architecture: The Bridge vs. JSI<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>For years, the Bridge was the heart of <strong>react native<\/strong>. It was asynchronous, which sounds good until you realize it\u2019s also non-deterministic. You send a message from JS: &#8220;Hey, change this background color to blue.&#8221; The Bridge serializes that into a JSON string, sends it to the Native side, which deserializes it and updates the UI. If the Bridge is busy\u2014say, because you&#8217;re fetching a 2MB JSON payload from <code>api.stripe.com\/v1\/events<\/code>\u2014your UI interaction lags. This is why <strong>react native<\/strong> apps often feel &#8220;janky&#8221; compared to native ones.<\/p>\n<p>The &#8220;New Architecture&#8221; replaces the Bridge with the JavaScript Interface (JSI). This is a game-changer, but it\u2019s also a massive migration headache. JSI allows JavaScript to hold a reference to a C++ host object. You can call methods on it directly. No more JSON serialization. No more asynchronous overhead for simple UI updates. But here is the catch: to use it, your third-party libraries must support it. Most don&#8217;t. You\u2019ll find yourself stuck in a hybrid state where half your app uses the old Bridge and the other half tries to use Fabric (the new UI renderer).<\/p>\n<blockquote><p>\n    Pro-tip: If you are starting a new project in 2024, enable the New Architecture immediately. Do not wait. Retrofitting it into a 2-year-old codebase is a recipe for a month-long regression testing nightmare.\n<\/p><\/blockquote>\n<pre><code>\n\/\/ Example of a TurboModule (New Architecture) definition\n\/\/ This is TypeScript, but it generates C++ code under the hood.\nimport type {TurboModule} from 'react-native';\nimport {TurboModuleRegistry} from 'react-native';\n\nexport interface Spec extends TurboModule {\n  getDeviceName(): string;\n  setStorageItem(key: string, value: string): Promise&lt;boolean&gt;;\n  \/\/ Note: JSI allows synchronous calls, but use them sparingly.\n  getHardwareIdSync(): string;\n}\n\nexport default TurboModuleRegistry.getEnforced&lt;Spec&gt;('DeviceHelper');\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Hermes_The_Engine_You_Cant_Ignore\"><\/span>Hermes: The Engine You Can&#8217;t Ignore<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you aren&#8217;t using the Hermes engine, you are doing it wrong. Period. In the early days, <strong>react native<\/strong> used the JavaScriptCore (JSC) engine\u2014the same one Safari uses. On iOS, it was fine because JSC is a system framework. On Android, you had to bundle the entire JSC engine into your APK, adding 20MB of bloat and terrible startup performance. <\/p>\n<p>Hermes is a small, lightweight JS engine optimized for mobile. Its biggest trick? Pre-compilation. Instead of parsing JS at runtime, Hermes compiles your JS into bytecode during the build process. This slashes &#8220;Time to Interactive&#8221; (TTI). However, Hermes has quirks. Its garbage collector is aggressive. If you are creating thousands of short-lived objects in a <code>useMemo<\/code> hook inside a high-frequency loop, you will see &#8220;GC pressure&#8221; pauses. I\u2019ve seen apps drop from 60fps to 15fps because someone was mapping over a large array inside a render function instead of using a selector.<\/p>\n<ul>\n<li>Hermes does not support <code>with<\/code> statements (good, you shouldn&#8217;t use them anyway).<\/li>\n<li>It has limited support for <code>Proxy<\/code> objects in older versions, which can break some state management libraries.<\/li>\n<li>The debugger uses the Chrome DevTools protocol, but it\u2019s finicky. If your app crashes on launch, the debugger usually won&#8217;t catch it because the engine hasn&#8217;t initialized yet.<\/li>\n<li>Memory profiling in Hermes requires using the <code>.heapsnapshot<\/code> format, which you can load into Chrome, but interpreting it requires understanding how C++ allocates memory for JS objects.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"The_Native_Module_Trap\"><\/span>The Native Module Trap<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Eventually, you will need to do something JS can&#8217;t do. Maybe it&#8217;s background geolocation that doesn&#8217;t get killed by the OS, or maybe it&#8217;s custom image processing using OpenCV. This is where the &#8220;React Native is easy&#8221; myth dies. You have to write a Native Module. <\/p>\n<p>On Android, this means Java or Kotlin. On iOS, Objective-C or Swift. But it&#8217;s not just the language; it&#8217;s the lifecycle. Your native module lives as a singleton. If you store state in your native module, you have to manually clear it when the JS bundle reloads. I once saw a bug where a user\u2019s session persisted across logouts because the &#8220;AuthModule&#8221; in Java was holding a static reference to a token that the JS side thought it had deleted.<\/p>\n<pre><code>\n\/\/ Android Native Module: The reality of boilerplate\npackage com.myapp.storage;\n\nimport com.facebook.react.bridge.ReactApplicationContext;\nimport com.facebook.react.bridge.ReactContextBaseJavaModule;\nimport com.facebook.react.bridge.ReactMethod;\nimport com.facebook.react.bridge.Promise;\nimport android.content.Context;\nimport android.content.SharedPreferences;\n\npublic class SecureStorageModule extends ReactContextBaseJavaModule {\n    private static ReactApplicationContext reactContext;\n\n    SecureStorageModule(ReactApplicationContext context) {\n        super(context);\n        reactContext = context;\n    }\n\n    @Override\n    public String getName() {\n        return \"SecureStorage\";\n    }\n\n    @ReactMethod\n    public void setItem(String key, String value, Promise promise) {\n        try {\n            SharedPreferences sharedPref = reactContext.getSharedPreferences(\"secret_prefs\", Context.MODE_PRIVATE);\n            SharedPreferences.Editor editor = sharedPref.edit();\n            editor.putString(key, value);\n            editor.apply();\n            promise.resolve(true);\n        } catch (Exception e) {\n            promise.reject(\"ERR_STORAGE\", e.getMessage());\n        }\n    }\n}\n<\/code><\/pre>\n<p>Notice the <code>Promise<\/code>. Everything across the bridge is a promise. If you have a tight loop that needs a value from native, you&#8217;re going to have a bad time. You&#8217;ll end up with &#8220;Promise hell&#8221; on the native side, which is even harder to debug than the JS version because the stack traces often disappear into the <code>libfb.so<\/code> binary.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"State_Management_Redux_is_a_Sledgehammer\"><\/span>State Management: Redux is a Sledgehammer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>People love to argue about Redux vs. Zustand vs. Context. In <strong>react native<\/strong>, the choice matters more because of the single-threaded nature of JS. If you use Redux and your state tree is a 5MB JSON object, every time you dispatch an action, Redux does a shallow compare of the tree. On a desktop i9, that&#8217;s 1ms. On a $150 Android phone, that&#8217;s 40ms. You just dropped two frames of animation because you dispatched a <code>KEYBOARD_OPEN<\/code> action.<\/p>\n<p>I prefer <strong>Zustand<\/strong> or <strong>MobX<\/strong>. Why? Because they allow for more granular updates. But even then, the real killer is the &#8220;Re-render Loop.&#8221; In a web browser, a few extra re-renders are usually fine. In <strong>react native<\/strong>, a re-render triggers a layout calculation in <strong>Yoga<\/strong> (the C++ layout engine). Yoga is fast, but it&#8217;s not free. If you have a deeply nested component tree, a single state change at the top can trigger hundreds of calls to <code>measure()<\/code> and <code>layout()<\/code> on the native side.<\/p>\n<p>Use <code>React.memo<\/code>. Use <code>useCallback<\/code>. Use <code>useMemo<\/code>. These aren&#8217;t &#8220;optimizations&#8221; in <strong>react native<\/strong>; they are requirements for a functional app. If you don&#8217;t believe me, turn on the &#8220;Perf Monitor&#8221; in the dev menu and watch your JS thread FPS drop to 0 when you type in a text input that isn&#8217;t properly memoized.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_Build_System_Where_Dreams_Go_to_Die\"><\/span>The Build System: Where Dreams Go to Die<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The most difficult part of <strong>react native<\/strong> isn&#8217;t the code. It&#8217;s the build system. You are dealing with <code>npm<\/code>, <code>CocoaPods<\/code>, and <code>Gradle<\/code> all at once. If one of them is unhappy, none of them are happy. <\/p>\n<p>Take <code>CocoaPods<\/code>. It\u2019s a Ruby-based dependency manager for iOS. If your machine has the wrong Ruby version (thanks, macOS default Ruby), <code>pod install<\/code> will fail with a cryptic error about <code>ffi<\/code>. Or maybe you&#8217;re on an M1\/M2 Mac and you need to run <code>arch -x86_64 pod install<\/code> because some legacy library hasn&#8217;t been updated for ARM. Then there&#8217;s <code>Gradle<\/code>. Android&#8217;s build system is a beast that consumes RAM like a black hole. If you don&#8217;t give your Gradle daemon at least 4GB of heap (<code>org.gradle.jvmargs=-Xmx4096m<\/code>), your builds will take 10 minutes and then fail with a <code>GC overhead limit exceeded<\/code> error.<\/p>\n<ul>\n<li><strong>The Node Modules Black Hole:<\/strong> Your <code>node_modules<\/code> folder will eventually reach 2GB. <code>rm -rf node_modules && npm install<\/code> is the &#8220;have you tried turning it off and on again&#8221; of the RN world.<\/li>\n<li><strong>Version Mismatches:<\/strong> <code>react-native<\/code> version 0.73.x might require <code>kotlinVersion = \"1.8.0\"<\/code>. If a plugin you use requires <code>1.9.0<\/code>, Gradle will throw a fit. You&#8217;ll spend your afternoon in <code>android\/build.gradle<\/code> overriding configurations.<\/li>\n<li><strong>Code Signing:<\/strong> Provisioning profiles and keystores. You will lose a week of your life to Apple&#8217;s &#8220;Missing Push Capability&#8221; emails because your <code>Entitlements.plist<\/code> wasn&#8217;t synced correctly by the CLI.<\/li>\n<li><strong>The Metro Bundler:<\/strong> Metro is the JS bundler. It&#8217;s fast, but it hates symlinks. If you&#8217;re using a monorepo (Lerna, Nx, Turborepo), you will need a <code>metro.config.js<\/code> that looks like an incantation from a dark magic ritual just to get it to find your shared packages.<\/li>\n<li><strong>Fastlane:<\/strong> If you aren&#8217;t using Fastlane to automate your deployments to TestFlight and Google Play, you are wasting hours every week. But Fastlane itself is another layer of Ruby that can break.<\/li>\n<li><strong>CI\/CD Latency:<\/strong> A typical native build on GitHub Actions takes 15-30 minutes. You cannot iterate quickly if your feedback loop is half an hour long. You need a Mac mini under someone&#8217;s desk or a very expensive M1-based CI runner.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"The_%E2%80%9CGotcha%E2%80%9D_The_Keyboard_and_the_Notch\"><\/span>The &#8220;Gotcha&#8221;: The Keyboard and the Notch<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Here is something no one tells you: handling the keyboard in <strong>react native<\/strong> is a nightmare. On iOS, the keyboard slides up and covers your inputs. On Android, the OS might resize the whole window, or it might just cover it, depending on the <code>windowSoftInputMode<\/code> in your <code>AndroidManifest.xml<\/code>. <\/p>\n<p>You\u2019ll reach for <code>KeyboardAvoidingView<\/code>. It won&#8217;t work. It will either jump too high or not high enough. You&#8217;ll end up using a third-party library like <code>react-native-keyboard-controller<\/code> because the built-in solution is fundamentally broken for complex layouts. Then there&#8217;s the &#8220;Safe Area.&#8221; Every phone has a notch, a punch-hole camera, or a rounded corner. If you don&#8217;t wrap your app in a <code>SafeAreaProvider<\/code>, your &#8220;Back&#8221; button will be hidden behind the system clock, and Apple will reject your app during review.<\/p>\n<blockquote><p>\n    Note to self: Always test on a device with a &#8220;Dynamic Island&#8221; and a device with a bottom &#8220;Home Indicator.&#8221; What looks good on an iPhone 8 looks like garbage on an iPhone 15 Pro.\n<\/p><\/blockquote>\n<h2><span class=\"ez-toc-section\" id=\"Performance_Profiling_Beyond_consolelog\"><\/span>Performance Profiling: Beyond console.log<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When your app is slow, <code>console.log<\/code> is useless. In fact, <code>console.log<\/code> makes it slower because the logs themselves have to be serialized and sent over the bridge to the debugger. I\u2019ve seen apps speed up by 20% just by removing debug logs in production (use <code>babel-plugin-transform-remove-console<\/code> for this).<\/p>\n<p>To actually fix performance, you need the <strong>Flashlight<\/strong> tool or the <strong>React DevTools<\/strong> profiler. You need to look at &#8220;Commit&#8221; times. If a commit takes more than 16ms, you are dropping frames. You need to look at the &#8220;Flamegraph.&#8221; Are you re-rendering the entire list because one item&#8217;s heart icon changed? That\u2019s a failure of your <code>memo<\/code> strategy. <\/p>\n<p>On Android, use <code>systrace<\/code>. It shows you exactly what the UI thread is doing. If you see long blocks of <code>Choreographer#doFrame<\/code>, the native side is struggling. If you see long blocks of <code>mqt_js<\/code>, your JavaScript is the bottleneck. Usually, it&#8217;s a bit of both, dancing together in a spiral of inefficiency.<\/p>\n<pre><code>\n\/\/ A common performance footgun\nconst MyComponent = () => {\n  const [items, setItems] = useState([1, 2, 3]);\n\n  \/\/ BAD: This function is recreated on every render\n  \/\/ Any child component receiving this as a prop will re-render\n  const handlePress = (id) => {\n    console.log('Pressed', id);\n  };\n\n  return (\n    &lt;FlatList \n      data={items}\n      renderItem={({item}) => &lt;ListItem onPress={() => handlePress(item.id)} \/&gt;} \/\/ EVEN WORSE: Inline arrow function\n    \/&gt;\n  );\n};\n\n\/\/ BETTER:\nconst MyComponentFixed = () => {\n  const [items, setItems] = useState([1, 2, 3]);\n\n  const handlePress = useCallback((id) => {\n    console.log('Pressed', id);\n  }, []);\n\n  const renderItem = useCallback(({item}) => (\n    &lt;ListItem id={item.id} onPress={handlePress} \/&gt;\n  ), [handlePress]);\n\n  return (\n    &lt;FlatList \n      data={items}\n      renderItem={renderItem}\n      keyExtractor={item => item.id.toString()}\n      removeClippedSubviews={true} \/\/ Crucial for large lists\n      maxToRenderPerBatch={10}\n      windowSize={5}\n    \/&gt;\n  );\n};\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"The_Upgrade_Path_A_Tale_of_Woe\"><\/span>The Upgrade Path: A Tale of Woe<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Upgrading <strong>react native<\/strong> is the single most painful task in software engineering. It\u2019s not like <code>npm update<\/code>. It\u2019s like performing a heart transplant while the patient is running a marathon. Between versions, the internal C++ APIs change, the Gradle plugin versions shift, and the CocoaPods structure gets reorganized. <\/p>\n<p>I once spent three days upgrading from 0.68 to 0.70. The culprit? A change in how <code>react-native-community\/cli<\/code> handled autolinking for native modules with custom search paths. The error message was just <code>Linker command failed with exit code 1<\/code>. I had to manually diff the <code>project.pbxproj<\/code> file\u2014a file that is notoriously human-unreadable\u2014to find a missing library reference. <\/p>\n<p>Always use the <strong>React Native Upgrade Helper<\/strong>. It\u2019s a web tool that shows you the diff between a clean project of your current version and a clean project of the target version. You have to manually apply those changes to your files. If you\u2019ve heavily customized your native folders, God help you.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Is_It_Worth_It\"><\/span>Is It Worth It?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>After a decade of SRE work, I&#8217;ve seen the &#8220;Native vs. Cross-Platform&#8221; war play out a dozen times. <strong>react native<\/strong> is not a silver bullet. It is a trade-off. You trade runtime performance and build-system stability for development speed and a unified codebase. For 90% of business apps\u2014CRUD apps, e-commerce, social media\u2014it is the right choice. But that other 10%? If you are building a high-performance video editor, a complex 3D game, or a real-time signal processing app, <strong>react native<\/strong> will be a constant source of friction.<\/p>\n<p>The &#8220;velocity&#8221; you gain in the first three months is often paid back with interest in the following two years as you fight the Bridge, the build system, and the upgrade cycle. You don&#8217;t get a &#8220;free&#8221; mobile app. You get a complex, multi-runtime system that requires a deep understanding of both web and mobile internals to maintain at scale.<\/p>\n<p>If you\u2019re going to use <strong>react native<\/strong>, stop treating it like a web project. Learn how <code>ProGuard<\/code> works. Learn how to read an Objective-C stack trace. Learn why <code>Lottie<\/code> animations can sometimes peg the CPU at 100%. The &#8220;magic&#8221; only works until it doesn&#8217;t, and when it fails, you&#8217;ll be glad you know what&#8217;s happening under the hood.<\/p>\n<p>Stop chasing the latest state management library and start looking at your frame budget. Your users don&#8217;t care if you use Redux or signals; they care that the app doesn&#8217;t freeze when they try to pay for their coffee. Optimize your Bridge traffic, use Hermes, and for the love of all that is holy, test on a $100 Android phone before you push to production.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Related_Articles\"><\/span>Related Articles<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Explore more insights and best practices:<\/p>\n<ul>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/docker-install-a-complete-step-by-step-setup-guide\/\">Docker Install A Complete Step By Step Setup Guide<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/10-javascript-best-practices-every-developer-should-know\/\">10 Javascript Best Practices Every Developer Should Know<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/how-to-block-microsoft-bookings-access-in-tenant\/\">How To Block Microsoft Bookings Access In Tenant<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>React Native: The Bridge is Out and Your App is OOM-Killed It was 3:00 AM on a Tuesday in 2021. I was the lead SRE for a fintech startup that had just launched a high-yield savings feature. We built the mobile app in react native because the &#8220;velocity&#8221; was supposed to be unmatched. We hit &#8230; <a title=\"React Native Guide: Build High-Performance Mobile Apps\" class=\"read-more\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\" aria-label=\"Read more  on React Native Guide: Build High-Performance Mobile Apps\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4915","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>React Native Guide: Build High-Performance Mobile Apps - ITSupportWale<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"React Native Guide: Build High-Performance Mobile Apps - ITSupportWale\" \/>\n<meta property=\"og:description\" content=\"React Native: The Bridge is Out and Your App is OOM-Killed It was 3:00 AM on a Tuesday in 2021. I was the lead SRE for a fintech startup that had just launched a high-yield savings feature. We built the mobile app in react native because the &#8220;velocity&#8221; was supposed to be unmatched. We hit ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\" \/>\n<meta property=\"og:site_name\" content=\"ITSupportWale\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-25T18:21:34+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"512\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Techie\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Techie\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\"},\"author\":{\"name\":\"Techie\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\"},\"headline\":\"React Native Guide: Build High-Performance Mobile Apps\",\"datePublished\":\"2026-10-25T18:21:34+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\"},\"wordCount\":2412,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\",\"name\":\"React Native Guide: Build High-Performance Mobile Apps - ITSupportWale\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\"},\"datePublished\":\"2026-10-25T18:21:34+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/itsupportwale.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"React Native Guide: Build High-Performance Mobile Apps\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"name\":\"ITSupportWale\",\"description\":\"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\",\"name\":\"itsupportwale\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"contentUrl\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"width\":1119,\"height\":144,\"caption\":\"itsupportwale\"},\"image\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\",\"name\":\"Techie\",\"sameAs\":[\"https:\/\/itsupportwale.com\",\"iswblogadmin\"],\"url\":\"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"React Native Guide: Build High-Performance Mobile Apps - ITSupportWale","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/","og_locale":"en_US","og_type":"article","og_title":"React Native Guide: Build High-Performance Mobile Apps - ITSupportWale","og_description":"React Native: The Bridge is Out and Your App is OOM-Killed It was 3:00 AM on a Tuesday in 2021. I was the lead SRE for a fintech startup that had just launched a high-yield savings feature. We built the mobile app in react native because the &#8220;velocity&#8221; was supposed to be unmatched. We hit ... Read more","og_url":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/","og_site_name":"ITSupportWale","article_publisher":"https:\/\/www.facebook.com\/Itsupportwale-298547177495978","article_published_time":"2026-10-25T18:21:34+00:00","og_image":[{"width":512,"height":512,"url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png","type":"image\/png"}],"author":"Techie","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Techie","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#article","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/"},"author":{"name":"Techie","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d"},"headline":"React Native Guide: Build High-Performance Mobile Apps","datePublished":"2026-10-25T18:21:34+00:00","mainEntityOfPage":{"@id":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/"},"wordCount":2412,"commentCount":0,"publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/","url":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/","name":"React Native Guide: Build High-Performance Mobile Apps - ITSupportWale","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/#website"},"datePublished":"2026-10-25T18:21:34+00:00","breadcrumb":{"@id":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/itsupportwale.com\/blog\/react-native-guide-build-high-performance-mobile-apps-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/itsupportwale.com\/blog\/"},{"@type":"ListItem","position":2,"name":"React Native Guide: Build High-Performance Mobile Apps"}]},{"@type":"WebSite","@id":"https:\/\/itsupportwale.com\/blog\/#website","url":"https:\/\/itsupportwale.com\/blog\/","name":"ITSupportWale","description":"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides","publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/itsupportwale.com\/blog\/#organization","name":"itsupportwale","url":"https:\/\/itsupportwale.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","contentUrl":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","width":1119,"height":144,"caption":"itsupportwale"},"image":{"@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Itsupportwale-298547177495978"]},{"@type":"Person","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d","name":"Techie","sameAs":["https:\/\/itsupportwale.com","iswblogadmin"],"url":"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/comments?post=4915"}],"version-history":[{"count":0,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4915\/revisions"}],"wp:attachment":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/media?parent=4915"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/categories?post=4915"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/tags?post=4915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}