<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adil Mezghouti</title>
    <description>The latest articles on DEV Community by Adil Mezghouti (@adilmezghouti).</description>
    <link>https://dev.to/adilmezghouti</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F315444%2F46e422d3-86be-4f51-8614-6187086ce9ec.jpeg</url>
      <title>DEV Community: Adil Mezghouti</title>
      <link>https://dev.to/adilmezghouti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adilmezghouti"/>
    <language>en</language>
    <item>
      <title>Polyfills, Shims, and Native Modules: Lessons from Building a React Native Crypto Wallet</title>
      <dc:creator>Adil Mezghouti</dc:creator>
      <pubDate>Mon, 10 Aug 2026 16:44:19 +0000</pubDate>
      <link>https://dev.to/adilmezghouti/polyfills-shims-and-native-modules-lessons-from-building-a-react-native-crypto-wallet-4acc</link>
      <guid>https://dev.to/adilmezghouti/polyfills-shims-and-native-modules-lessons-from-building-a-react-native-crypto-wallet-4acc</guid>
      <description>&lt;p&gt;&lt;strong&gt;Preface:&lt;/strong&gt; &lt;em&gt;This article is about my experience building a crypto mobile wallet back in 2021.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Building a crypto wallet in React Native is a masterclass in edge-case architecture. Unlike standard mobile applications that simply fetch JSON from a REST API, a crypto wallet acts as an isolated cryptographic engine. It must generate entropy, derive keys, sign transactions, encode raw binary payloads, and communicate with decentralized networks.&lt;/p&gt;

&lt;p&gt;When you attempt to bring standard Web3 JavaScript libraries into React Native, you quickly discover a fundamental disconnect: most Web3 packages were written assuming either a full Node.js runtime or a web browser environment. React Native's JavaScript engine (Hermes or JavaScriptCore) provides neither.&lt;/p&gt;

&lt;p&gt;To make a mobile crypto wallet work, you inevitably have to master three distinct strategies: &lt;strong&gt;Polyfilling&lt;/strong&gt;, &lt;strong&gt;Shimming&lt;/strong&gt;, and &lt;strong&gt;Native Modules&lt;/strong&gt;. Here is how each strategy fits into building a wallet, when to reach for them, and how the ecosystem has evolved.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Strategies in a Wallet Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                       ┌──────────────────────────────────────────┐
                       │       React Native Wallet Application    │
                       └────────────────────┬─────────────────────┘
                                            │
        ┌───────────────────────────────────┼───────────────────────────────────┐
        ▼                                   ▼                                   ▼
┌───────────────────────┐       ┌───────────────────────┐       ┌───────────────────────┐
│       POLYFILLS       │       │         SHIMS         │       │    NATIVE MODULES     │
├───────────────────────┤       ├───────────────────────┤       ├───────────────────────┤
│ • crypto.getRandom    │       │ • global.Buffer       │       │ • iOS Secure Enclave  │
│   Values              │       │ • readable-stream     │       │ • Android Keystore    │
│ • TextEncoder/Decoder │       │ • path / events       │       │ • C++ secp256k1 via   │
│ • URL/URLSearchParams │       │   (via Metro aliases) │       │   JSI for fast signing│
└───────────────────────┘       └───────────────────────┘       └───────────────────────┘

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Polyfilling: Restoring Missing Web Standards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it is:&lt;/strong&gt; Code that detects if a standard Web API exists in the JavaScript runtime. If missing, it dynamically attaches a spec-compliant JS implementation directly to the global scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallet Context:&lt;/strong&gt; Web3 SDKs (like Ethers.js, Viem, or WalletConnect) rely heavily on browser primitives for RPC formatting, address validation, and entropy generation. Without polyfills, functions expecting &lt;code&gt;URL&lt;/code&gt; or &lt;code&gt;TextEncoder&lt;/code&gt; crash immediately.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Polyfilling entropy generation for bip39 seed phrase generation&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-get-random-values&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Now standard Web Crypto entropy works globally in JS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRandomValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Shimming: Adapting Node.js Ecosystem Dependencies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it is:&lt;/strong&gt; Intercepting API calls to wrap, adapt, or alias non-standard environments (specifically Node.js built-in libraries) so they run inside React Native.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallet Context:&lt;/strong&gt; Core crypto primitives like &lt;code&gt;bip39&lt;/code&gt;, &lt;code&gt;ethereumjs-util&lt;/code&gt;, &lt;code&gt;bs58&lt;/code&gt;, and &lt;code&gt;hdkey&lt;/code&gt; were originally written for Node.js. They rely on built-ins like &lt;code&gt;Buffer&lt;/code&gt;, &lt;code&gt;stream&lt;/code&gt;, and &lt;code&gt;crypto&lt;/code&gt;. Metro doesn't resolve these by default, requiring shims and bundler aliases to map them to React Native JS equivalents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  1. Global Injection (In your entry point, e.g., &lt;code&gt;index.js&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;Before any Web3 or crypto library imports execute, you inject required Node globals into &lt;code&gt;globalThis&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In index.js / entry point&lt;/span&gt;
&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-buffer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Metro Bundler Aliasing (&lt;code&gt;metro.config.js&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;Injecting globals isn't enough on its own—when a package internally executes &lt;code&gt;require('crypto')&lt;/code&gt; or &lt;code&gt;require('stream')&lt;/code&gt;, Metro will still fail to resolve the module. You must configure Metro to alias Node's built-in modules to React Native-compatible browser/JS polyfill packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// metro.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getDefaultConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mergeConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native/metro-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getDefaultConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Map Node.js core modules to RN-compatible npm packages&lt;/span&gt;
    &lt;span class="na"&gt;extraNodeModules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-quick-crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readable-stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-buffer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Native Modules (TurboModules / JSI): Hardware Security &amp;amp; High-Perf C++
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it is:&lt;/strong&gt; Writing native code (Swift/Objective-C on iOS, Kotlin/Java on Android, or C++ via JSI) to expose native capabilities, security hardware, or compiled C/C++ libraries to JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallet Context:&lt;/strong&gt; A pure JavaScript engine running heavy cryptographic routines can choke the single-threaded event loop, leading to very poor performance.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>reactnative</category>
      <category>cryptocurrency</category>
      <category>crypto</category>
      <category>web3</category>
    </item>
    <item>
      <title>Persisting RN Settings Across Reinstalls Without User Accounts</title>
      <dc:creator>Adil Mezghouti</dc:creator>
      <pubDate>Thu, 06 Aug 2026 14:32:40 +0000</pubDate>
      <link>https://dev.to/adilmezghouti/persisting-rn-settings-across-reinstalls-without-user-accounts-h40</link>
      <guid>https://dev.to/adilmezghouti/persisting-rn-settings-across-reinstalls-without-user-accounts-h40</guid>
      <description>&lt;p&gt;A while back, I worked on a React Native app that had &lt;strong&gt;no support for user sign-ups or accounts&lt;/strong&gt;. Despite that, we had a clear requirement: &lt;strong&gt;preserve user customizations across app installs.&lt;/strong&gt;&lt;br&gt;
Users needed their custom theme choices, language/locale settings, and favorited items to survive if they deleted and reinstalled the app. Furthermore, we needed to keep their &lt;strong&gt;anonymous analytics IDs&lt;/strong&gt; persistent so we wouldn't pollute our data pipeline with "duplicate" new users every time someone reinstalled.&lt;/p&gt;

&lt;p&gt;Without a backend database or user ID to attach data to, I solved this by leveraging &lt;code&gt;@react-native-async-storage/async-storage&lt;/code&gt; alongside the built-in native OS backup mechanisms (iCloud on iOS and Google Auto Backup on Android). Here is how it works, what to watch out for, and how to set it up.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Requirements, Constraints &amp;amp; User Cost
&lt;/h2&gt;

&lt;p&gt;Before relying on native backups, you need to be aware of how the OS handles state restoration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Device Backup Prerequisite:&lt;/strong&gt; This strategy relies on the user having OS-level backups toggled on (&lt;strong&gt;Settings &amp;gt; Apple Account &amp;gt; iCloud Backup&lt;/strong&gt; on iOS or &lt;strong&gt;Settings &amp;gt; Google &amp;gt; Backup&lt;/strong&gt; on Android). If a user turns this off, state resets on reinstall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Cost for Users:&lt;/strong&gt; Users do &lt;strong&gt;not&lt;/strong&gt; need paid cloud storage tiers:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Android:&lt;/strong&gt; Google Auto Backup gives up to 25 MB per app for free—and it is &lt;strong&gt;completely exempt&lt;/strong&gt; from the user's 15 GB personal Google Drive quota.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS:&lt;/strong&gt; Settings payloads are tiny JSON files (&amp;lt; 100 KB) that consume virtually zero space in Apple's free 5 GB iCloud tier.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Latency Guardrails:&lt;/strong&gt; Never store sensitive tokens or credentials in &lt;code&gt;AsyncStorage&lt;/code&gt; backup files (use Keychain/KeyStore instead). Also, keep in mind that OS cloud snapshots trigger asynchronously (usually on Wi-Fi while charging). An immediate reinstall seconds after a setting change might restore the previous snapshot.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  2. Code Implementation
&lt;/h2&gt;

&lt;p&gt;Instead of cluttering storage with isolated keys, consolidate your guest preferences and anonymous analytics ID into a single schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-async-storage/async-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;GuestAppState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;analyticsId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;favorites&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Array of favorited item IDs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;STORAGE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@app_guest_state_v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;saveGuestState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GuestAppState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STORAGE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to persist guest state:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadGuestState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GuestAppState&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STORAGE_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to hydrate guest state:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works Under the Hood
&lt;/h3&gt;

&lt;p&gt;When a user reinstalls the app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;AsyncStorage&lt;/code&gt; writes keys to standard internal storage locations (iOS &lt;code&gt;Documents&lt;/code&gt; directory / Android internal SQLite/Key-Value files).&lt;/li&gt;
&lt;li&gt;The native OS includes these files in its scheduled cloud snapshot.&lt;/li&gt;
&lt;li&gt;Upon reinstalling, the OS restores the application sandbox files &lt;strong&gt;before&lt;/strong&gt; the React Native JavaScript bundle executes its initial boot.&lt;/li&gt;
&lt;li&gt;When your app mounts, &lt;code&gt;loadGuestState()&lt;/code&gt; reads the restored JSON file as if the app was never uninstalled—preserving theme, favorites, and the original &lt;code&gt;analyticsId&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Essential Native Configuration
&lt;/h2&gt;

&lt;p&gt;For native backups to work smoothly across installations, you need a few minor native file configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Android Setup (&lt;code&gt;android/app/src/main&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Ensure &lt;code&gt;android:allowBackup="true"&lt;/code&gt; is set in &lt;code&gt;AndroidManifest.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- AndroidManifest.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt;
    &lt;span class="na"&gt;android:allowBackup=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;android:fullBackupContent=&lt;/span&gt;&lt;span class="s"&gt;"@xml/backup_rules"&lt;/span&gt;
    &lt;span class="na"&gt;android:dataExtractionRules=&lt;/span&gt;&lt;span class="s"&gt;"@xml/data_extraction_rules"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define explicit rules in &lt;code&gt;res/xml/data_extraction_rules.xml&lt;/code&gt; (for Android 12+) to ensure &lt;code&gt;AsyncStorage&lt;/code&gt; databases and shared preferences are backed up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;data-extraction-rules&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;cloud-backup&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;domain=&lt;/span&gt;&lt;span class="s"&gt;"sharedpref"&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;include&lt;/span&gt; &lt;span class="na"&gt;domain=&lt;/span&gt;&lt;span class="s"&gt;"database"&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/cloud-backup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/data-extraction-rules&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  iOS Setup
&lt;/h3&gt;

&lt;p&gt;iOS automatically backs up the app's &lt;code&gt;Documents&lt;/code&gt; directory to iCloud by default. No Xcode configuration is required unless you manually flag files using &lt;code&gt;NSURLIsExcludedFromBackupKey&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-Up
&lt;/h2&gt;

&lt;p&gt;Relying on native OS cloud backups for &lt;code&gt;AsyncStorage&lt;/code&gt; is an effective way to preserve user customizations in accountless React Native apps. You keep user preferences intact, avoid backend infrastructure costs, maintain accurate analytics identity, and never cost your users a dime in cloud storage fees.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>backup</category>
    </item>
    <item>
      <title>5 React Native Interview Questions You must know how to solve</title>
      <dc:creator>Adil Mezghouti</dc:creator>
      <pubDate>Sun, 19 Jul 2026 14:01:59 +0000</pubDate>
      <link>https://dev.to/adilmezghouti/5-react-native-interview-questions-you-must-know-how-to-solve-2fhg</link>
      <guid>https://dev.to/adilmezghouti/5-react-native-interview-questions-you-must-know-how-to-solve-2fhg</guid>
      <description>&lt;p&gt;If you're prepping for a React Native interview, the truth is that most companies aren't testing whether you know some obscure API, they're testing whether you can build small, correct, and stateful UI under time pressure. Here are five patterns that show up constantly, what they're actually testing, and the mistakes that trip people up.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Stepper Counter (useState basics)
&lt;/h2&gt;

&lt;p&gt;The simplest possible test: a number, a &lt;code&gt;+&lt;/code&gt; button, a &lt;code&gt;-&lt;/code&gt; button. Trivial to get &lt;em&gt;working&lt;/em&gt;, easy to get &lt;em&gt;wrong&lt;/em&gt; in the details interviewers actually care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are you mutating state directly, or going through the setter?&lt;/li&gt;
&lt;li&gt;Does rapid clicking behave correctly, or are you reading stale state from a closure&lt;/li&gt;
&lt;li&gt;(&lt;code&gt;setCount(count + 1)&lt;/code&gt; vs &lt;code&gt;setCount(c =&amp;gt; c + 1)&lt;/code&gt;)?&lt;/li&gt;
&lt;li&gt;Did you clamp the range, if the spec asked for one?
If you can't explain &lt;em&gt;why&lt;/em&gt; the functional updater form matters, that's the tell an interviewer is listening for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. The Todo List (list state + keys)
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;useState&lt;/code&gt; collides with arrays and objects, and where most bugs live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are you spreading into a new array/object on every update, or mutating in place (which won't re-render, or will just be wrong with React 19's stricter expectations)?&lt;/li&gt;
&lt;li&gt;Are you using a stable &lt;code&gt;key&lt;/code&gt; (an id), not the array index, especially once delete/reorder is in the mix?&lt;/li&gt;
&lt;li&gt;Toggling "done" on one item shouldn't re-render the whole list conceptually, even if in practice RN doesn't punish you the way a huge web list might.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. The Tip Calculator (derived state)
&lt;/h2&gt;

&lt;p&gt;The trap here is state you don't need. A tip calculator has exactly one piece of real state, the bill amount and the tip percentage, and the tip/total are &lt;em&gt;derived&lt;/em&gt;, not stored. Candidates who reach for a third &lt;code&gt;useState&lt;/code&gt; for the computed total are demonstrating a habit that causes real bugs later: stored values that can drift out of sync with their inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Live Search Filter (controlled input + performance instinct)
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;TextInput&lt;/code&gt; that filters a list as you type. Functionally simple, but it's easy to get wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do you filter on every keystroke against the full source list (correct, and fine at small scale), or accidentally filter against the already-filtered list (a classic bug that quietly breaks "undo" a character)?&lt;/li&gt;
&lt;li&gt;Do you know &lt;em&gt;when&lt;/em&gt; you'd reach for debouncing, even if this list is small enough not to need it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Star Rating (interaction + accessibility instinct)
&lt;/h2&gt;

&lt;p&gt;A row of tappable stars that reflects and sets a rating. This tests something the other four don't: translating a design into discrete interactive elements, plus whether you think about accessibility&lt;br&gt;
by default (does each star have an accessible label like "Rate 3 stars," or is it just a bare &lt;code&gt;Pressable&lt;/code&gt; with an icon?).&lt;/p&gt;




&lt;h2&gt;
  
  
  Practicing these for real
&lt;/h2&gt;

&lt;p&gt;Reading about these patterns only gets you so far, you need to actually write the component and see it render. I built &lt;strong&gt;&lt;a href="https://rnprep.dev" rel="noopener noreferrer"&gt;rnprep.dev&lt;/a&gt;&lt;/strong&gt; for exactly this: a live CodeMirror editor next to a real React Native preview (self-hosted &lt;code&gt;react-native-web&lt;/code&gt; + Babel, not a hosted simulator or iframe), covering these five problems plus AI-graded feedback on your solution. No signup, no API key needed.&lt;/p&gt;

&lt;p&gt;If you've got a pattern you think should be on this list, the problem set is &lt;a href="https://github.com/adilmezghouti/rn-playground" rel="noopener noreferrer"&gt;open source&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>interview</category>
      <category>javascript</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
