<?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: running squirrel</title>
    <description>The latest articles on DEV Community by running squirrel (@running_squirrel).</description>
    <link>https://dev.to/running_squirrel</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2519384%2F5e4a9b9f-40a2-44c0-98f3-cef20f69118b.png</url>
      <title>DEV Community: running squirrel</title>
      <link>https://dev.to/running_squirrel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/running_squirrel"/>
    <language>en</language>
    <item>
      <title>Parsing hundreds of megabytes of JSON in milliseconds in React Native</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Sun, 17 May 2026 13:11:37 +0000</pubDate>
      <link>https://dev.to/running_squirrel/parsing-hundreds-of-megabytes-of-json-in-milliseconds-in-react-native-5c96</link>
      <guid>https://dev.to/running_squirrel/parsing-hundreds-of-megabytes-of-json-in-milliseconds-in-react-native-5c96</guid>
      <description>&lt;p&gt;&lt;em&gt;How &lt;code&gt;JSON.parse&lt;/code&gt; materializes entire documents in JavaScript, and how &lt;a href="https://github.com/ifeoluwak/react-native-fast-json" rel="noopener noreferrer"&gt;react-native-fast-json&lt;/a&gt; uses native simdjson + lazy &lt;code&gt;JsonView&lt;/code&gt; access to change the cost model in React Native.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ifeoluwak/react-native-fast-json" rel="noopener noreferrer"&gt;react-native-fast-json&lt;/a&gt;&lt;/strong&gt; is an open-source React Native library that wraps &lt;strong&gt;simdjson&lt;/strong&gt; in C++ and exposes a lazy &lt;strong&gt;&lt;code&gt;JsonView&lt;/code&gt;&lt;/strong&gt; through &lt;a href="https://nitro.margelo.com/" rel="noopener noreferrer"&gt;Nitro Modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most teams treat JSON parsing as “cheap” because API responses are small. The mental model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bytes on wire → JSON.parse → plain objects in JS → app logic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That model breaks when the payload is &lt;strong&gt;hundreds of megabytes&lt;/strong&gt;. The dominant cost is not “JSON syntax is slow” in the abstract, it is &lt;strong&gt;allocating and wiring up a full value tree in the JavaScript heap&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What &lt;code&gt;JSON.parse&lt;/code&gt; actually does in React Native
&lt;/h2&gt;

&lt;p&gt;When you call &lt;code&gt;JSON.parse&lt;/code&gt; (or &lt;code&gt;await response.json()&lt;/code&gt;), the engine:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Holds the &lt;strong&gt;UTF-16/UTF-8 string&lt;/strong&gt; (or an internal representation of the body)&lt;/li&gt;
&lt;li&gt;Walks the entire document&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;every&lt;/strong&gt; object, array, number, boolean, and string, creates &lt;strong&gt;JavaScript values&lt;/strong&gt; with engine overhead (hidden classes, property storage, array backing stores, interned strings, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a &lt;strong&gt;~250 MB&lt;/strong&gt; file, outcomes depend heavily on &lt;strong&gt;platform and available RAM&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Typical cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-second freezes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single-threaded parse + massive allocation on the JS thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory far above file size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JS object graph overhead (often &lt;strong&gt;~2–4×&lt;/strong&gt; the raw JSON size in bad cases)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OOM / process kill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Peak JS heap + retained tree + rest of the app&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On the &lt;strong&gt;&lt;code&gt;data_250mb.json&lt;/code&gt;&lt;/strong&gt; fixture in our tests: &lt;strong&gt;iOS&lt;/strong&gt; could complete &lt;code&gt;JSON.parse&lt;/code&gt; but only with &lt;strong&gt;extreme CPU and memory spikes&lt;/strong&gt;; &lt;strong&gt;Android&lt;/strong&gt; &lt;strong&gt;always crashed&lt;/strong&gt; before parse finished, making &lt;code&gt;JSON.parse&lt;/code&gt; &lt;strong&gt;impossible&lt;/strong&gt; for that payload on Android, while native &lt;code&gt;parseFile&lt;/code&gt; worked on both platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benchmark fixture (source)
&lt;/h3&gt;

&lt;p&gt;Measurements in this repo use the public &lt;strong&gt;~250 MB&lt;/strong&gt; JSON from &lt;a href="https://github.com/antonmedv/json-examples" rel="noopener noreferrer"&gt;antonmedv/json-examples&lt;/a&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repository&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/antonmedv/json-examples" rel="noopener noreferrer"&gt;https://github.com/antonmedv/json-examples&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/antonmedv/json-examples/blob/master/data_250mb.json" rel="noopener noreferrer"&gt;&lt;code&gt;data_250mb.json&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Raw URL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://github.com/antonmedv/json-examples/raw/refs/heads/master/data_250mb.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://github.com/ifeoluwak/react-native-fast-json/tree/main/example" rel="noopener noreferrer"&gt;example app&lt;/a&gt; downloads that URL, caches it on disk, then calls &lt;code&gt;parseFile&lt;/code&gt; on the local path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measured results (&lt;code&gt;parseFile&lt;/code&gt;, release builds, physical devices)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Time to root &lt;code&gt;JsonView&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;CPU / memory (observed)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~100 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Stable&lt;/strong&gt;, no long CPU peg, no runaway JS heap growth during parse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Android&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~500 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Stable&lt;/strong&gt;, same qualitative behavior as iOS, slower wall time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;JSON.parse&lt;/code&gt; / &lt;code&gt;response.json()&lt;/code&gt;&lt;/strong&gt; on the same fixture:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;&lt;code&gt;JSON.parse&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;parseFile&lt;/code&gt; + lazy &lt;code&gt;JsonView&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Many seconds&lt;/strong&gt;; &lt;strong&gt;extreme&lt;/strong&gt; CPU and memory spikes (~&lt;strong&gt;1.2 GB&lt;/strong&gt; JS heap ballpark)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~100 ms&lt;/strong&gt;; CPU and memory &lt;strong&gt;stable&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Android&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Crash&lt;/strong&gt;, could &lt;strong&gt;not&lt;/strong&gt; complete parse&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~500 ms&lt;/strong&gt;; CPU and memory &lt;strong&gt;stable&lt;/strong&gt; (~&lt;strong&gt;400 MB&lt;/strong&gt; mostly &lt;strong&gt;native&lt;/strong&gt; buffer)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The second row is &lt;strong&gt;not&lt;/strong&gt; “free memory.” The file still occupies roughly &lt;strong&gt;file size + simdjson padding&lt;/strong&gt; in native memory. The win is &lt;strong&gt;avoiding a second full copy as a giant JS object graph&lt;/strong&gt; until you explicitly materialize pieces.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why “read file as string, then &lt;code&gt;JSON.parse&lt;/code&gt;” can be worse at peak
&lt;/h2&gt;

&lt;p&gt;A common variant:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;data&lt;/span&gt; &lt;span class="o"&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;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At peak you may briefly hold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;entire file as one JS string&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;entire parsed tree&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Parser scratch allocations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;response.json()&lt;/code&gt; can sometimes avoid exposing one giant application-level string, but the &lt;strong&gt;end state&lt;/strong&gt; is still the same: a full tree in JS. For large files, &lt;strong&gt;peak heap&lt;/strong&gt; is the killer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The technique: how react-native-fast-json does it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ifeoluwak/react-native-fast-json" rel="noopener noreferrer"&gt;react-native-fast-json&lt;/a&gt; is what makes the native lazy model practical in React Native. Instead of returning a plain object from &lt;code&gt;JSON.parse&lt;/code&gt;, it shifts work across a different boundary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file bytes → native buffer (simdjson) → JsonView handle → read paths on demand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Native buffer (simdjson)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;parseFile&lt;/code&gt; loads the file into a &lt;strong&gt;padded&lt;/strong&gt; native buffer (&lt;code&gt;simdjson::padded_string::load&lt;/code&gt;). Parsing runs in &lt;strong&gt;C++&lt;/strong&gt; with &lt;a href="https://github.com/simdjson/simdjson" rel="noopener noreferrer"&gt;simdjson&lt;/a&gt; (SIMD-accelerated, widely used for large JSON).&lt;/p&gt;

&lt;p&gt;The document’s canonical bytes live in &lt;strong&gt;native memory&lt;/strong&gt;, not as nested JS objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lazy &lt;code&gt;JsonView&lt;/code&gt; (Nitro hybrid object)
&lt;/h3&gt;

&lt;p&gt;The root returned to JavaScript is a &lt;strong&gt;&lt;code&gt;JsonView&lt;/code&gt;&lt;/strong&gt;, a &lt;a href="https://nitro.margelo.com/" rel="noopener noreferrer"&gt;Nitro&lt;/a&gt; hybrid object backed by C++. Calling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getValue('metadata')&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;atPath('$.a.b.c')&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;asString()&lt;/code&gt; on a scalar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…does &lt;strong&gt;targeted&lt;/strong&gt; native work and only crosses the bridge with &lt;strong&gt;small&lt;/strong&gt; results (another &lt;code&gt;JsonView&lt;/code&gt; handle or a primitive), not the whole document.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Materialization is explicit and expensive
&lt;/h3&gt;

&lt;p&gt;When you call:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;asObject()&lt;/code&gt;&lt;/strong&gt;, subtree becomes a JS-friendly map/array structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;rawJson()&lt;/code&gt;&lt;/strong&gt;, subtree becomes a JS string&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…you have chosen to &lt;strong&gt;pay the JS heap cost&lt;/strong&gt; for that slice. On a 250 MB document, calling these on the &lt;strong&gt;root&lt;/strong&gt; is equivalent to opting back into the problem you avoided.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;HybridFastJson&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;cpp/HybridFastJson.cpp&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;parseFile(path)&lt;/code&gt;, load file, construct &lt;code&gt;HybridJsonView&lt;/code&gt;, &lt;strong&gt;cache&lt;/strong&gt; by path string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parseString(str)&lt;/code&gt;, copy string into native view (&lt;strong&gt;not&lt;/strong&gt; path-cached)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;release(path)&lt;/code&gt;, erase cache entry for that path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;HybridJsonView&lt;/code&gt;&lt;/strong&gt;, navigation, path helpers, scalar coercion, optional materialization.&lt;/p&gt;

&lt;p&gt;Until &lt;code&gt;release(path)&lt;/code&gt;, a cached &lt;code&gt;parseFile&lt;/code&gt; keeps the &lt;strong&gt;full native buffer&lt;/strong&gt; alive even if JS drops its &lt;code&gt;JsonView&lt;/code&gt; reference, plan releases when the flow ends.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you still pay for (honest accounting)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Still there?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File-sized native memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes, roughly &lt;strong&gt;JSON size + padding&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parse CPU&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes, but native simdjson is much faster than building a JS tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JS heap for the whole tree&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;No&lt;/strong&gt;, unless you &lt;code&gt;asObject()&lt;/code&gt; / &lt;code&gt;rawJson()&lt;/code&gt; large parts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bridge traffic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per access; keep reads coarse-grained for huge docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Path cache&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;parseFile&lt;/code&gt; retains buffer until &lt;strong&gt;&lt;code&gt;release(path)&lt;/code&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is &lt;strong&gt;no zero memory overhead&lt;/strong&gt;. The claim that holds up is: &lt;strong&gt;near-zero &lt;em&gt;additional&lt;/em&gt; JS heap for the full document&lt;/strong&gt; while you navigate lazily.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why milliseconds (or low hundreds of ms) are plausible for hundreds of MB
&lt;/h2&gt;

&lt;p&gt;simdjson is designed for throughput on large valid JSON. On the &lt;a href="https://github.com/antonmedv/json-examples/blob/master/data_250mb.json" rel="noopener noreferrer"&gt;&lt;code&gt;data_250mb.json&lt;/code&gt;&lt;/a&gt; fixture, &lt;strong&gt;&lt;code&gt;parseFile&lt;/code&gt; after the file is on disk&lt;/strong&gt; landed at &lt;strong&gt;~100 ms on iOS&lt;/strong&gt; and &lt;strong&gt;~500 ms on Android&lt;/strong&gt; in our release builds, with &lt;strong&gt;stable CPU and memory&lt;/strong&gt;. By contrast, &lt;strong&gt;&lt;code&gt;JSON.parse&lt;/code&gt; on iOS&lt;/strong&gt; took &lt;strong&gt;many seconds&lt;/strong&gt; with &lt;strong&gt;extreme spikes&lt;/strong&gt;; on &lt;strong&gt;Android&lt;/strong&gt; it &lt;strong&gt;always crashed&lt;/strong&gt;, so native parse was the only viable option there.&lt;/p&gt;

&lt;p&gt;Caveats when you reproduce benchmarks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fixture&lt;/strong&gt;, use the same public file or disclose yours&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold vs warm&lt;/strong&gt; storage (first read after download vs re-parse)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform&lt;/strong&gt;, Android was ~5× slower than iOS in our tests; do not assume one number for all devices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device tier&lt;/strong&gt; and storage speed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON shape&lt;/strong&gt; (depth, string density) affects constant factors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug vs release&lt;/strong&gt; native builds, ship measurements on &lt;strong&gt;release&lt;/strong&gt; binaries&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison table (same fixture, measured + observed)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;JSON.parse&lt;/code&gt; (our tests)&lt;/th&gt;
&lt;th&gt;Native &lt;code&gt;JsonView&lt;/code&gt; (&lt;code&gt;parseFile&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Completes after &lt;strong&gt;many seconds&lt;/strong&gt;; &lt;strong&gt;extreme&lt;/strong&gt; CPU/memory spikes&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~100 ms&lt;/strong&gt;; &lt;strong&gt;stable&lt;/strong&gt; CPU/memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Android&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Crash&lt;/strong&gt;, parse &lt;strong&gt;not possible&lt;/strong&gt; on ~250 MB&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~500 ms&lt;/strong&gt;; &lt;strong&gt;stable&lt;/strong&gt; CPU/memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full JS object graph (when it survives)&lt;/td&gt;
&lt;td&gt;Native padded buffer (~file size)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI thread risk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High during parse&lt;/td&gt;
&lt;td&gt;Lower; still avoid huge sync work in JS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best access pattern&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Whole-tree mutation&lt;/td&gt;
&lt;td&gt;Few paths / scalars / wildcards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Foot-guns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Retaining whole &lt;code&gt;data&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;asObject()&lt;/code&gt; / &lt;code&gt;rawJson()&lt;/code&gt; on huge nodes; never calling &lt;code&gt;release&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Wildcards and paths
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;atPath('$.a.b.c')&lt;/code&gt;&lt;/strong&gt;, simple dotted segments, no &lt;code&gt;[index]&lt;/code&gt; in the path string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;atPathWithWildcard('$.items[*].id')&lt;/code&gt;&lt;/strong&gt;, dynamic segments; returns &lt;code&gt;string[] | null&lt;/code&gt; for matched scalar strings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For very large documents, prefer &lt;strong&gt;narrow&lt;/strong&gt; paths over scanning wildcards across the whole tree unless you have measured the cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  When native lazy parsing is the wrong tool
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Not a common use case, prefer better alternatives
&lt;/h3&gt;

&lt;p&gt;Shipping &lt;strong&gt;~250 MB JSON&lt;/strong&gt; to a phone is a &lt;strong&gt;smell&lt;/strong&gt;, not a pattern. We benchmark it because it stress-tests the parser and matches real legacy pain, not because every app should do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try these first&lt;/strong&gt; (usually cheaper than optimizing parse):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don’t send the file&lt;/strong&gt;, paginate, stream, or return only fields the UI needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t use JSON on the wire&lt;/strong&gt;, schema-driven binary formats decode faster and smaller.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t keep one blob&lt;/strong&gt;, SQLite (or similar) with indexes for the queries you actually run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t parse on the critical path&lt;/strong&gt;, generate summaries or shards on the server; sync deltas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Native lazy parsing is a &lt;strong&gt;mitigation&lt;/strong&gt; when you are locked into large JSON. It is not a substitute for a sane data contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  When this library still does not help enough
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Small payloads, &lt;code&gt;JSON.parse&lt;/code&gt; is simpler and fast enough.&lt;/li&gt;
&lt;li&gt;You need the entire document in JS anyway, you will materialize everything eventually; measure whether native parse + bulk &lt;code&gt;asObject()&lt;/code&gt; is still a win.&lt;/li&gt;
&lt;li&gt;Heavy in-place mutation of arbitrary subtrees in JS, work on plain objects.&lt;/li&gt;
&lt;li&gt;You cannot hold &lt;strong&gt;file-sized native RAM&lt;/strong&gt; (low-RAM devices + multiple huge files), budget and serialize access; even native buffers are ~file size.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Benchmark methodology
&lt;/h2&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fastJson&lt;/span&gt; &lt;span class="p"&gt;}&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-fast-json&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;root&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;fastJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/path/to/large.json&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;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;metadata&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;asString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;fastJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/path/to/large.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fixture&lt;/strong&gt;, &lt;a href="https://github.com/antonmedv/json-examples/blob/master/data_250mb.json" rel="noopener noreferrer"&gt;&lt;code&gt;data_250mb.json&lt;/code&gt;&lt;/a&gt; from &lt;a href="https://github.com/antonmedv/json-examples" rel="noopener noreferrer"&gt;antonmedv/json-examples&lt;/a&gt;, via
&lt;code&gt;https://github.com/antonmedv/json-examples/raw/refs/heads/master/data_250mb.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RN Version&lt;/strong&gt; 0.85.0, New Architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device&lt;/strong&gt;, physical iOS and Android (document model, OS, RN version, Hermes on/off).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build&lt;/strong&gt;, release native binary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scenarios&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;A: &lt;code&gt;response.json()&lt;/code&gt; or &lt;code&gt;JSON.parse&lt;/code&gt; after full string in memory&lt;/li&gt;
&lt;li&gt;B: download/cache to disk → &lt;code&gt;parseFile(localPath)&lt;/code&gt; → read N fields → &lt;code&gt;release(path)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt;, wall time to root &lt;code&gt;JsonView&lt;/code&gt;, JS heap snapshot, CPU/memory stability in Instruments / Android Studio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Our results&lt;/strong&gt;, &lt;code&gt;parseFile&lt;/code&gt;: iOS &lt;strong&gt;~100 ms&lt;/strong&gt;, Android &lt;strong&gt;~500 ms&lt;/strong&gt;, CPU/memory &lt;strong&gt;stable&lt;/strong&gt;. &lt;code&gt;JSON.parse&lt;/code&gt;: iOS &lt;strong&gt;many seconds&lt;/strong&gt; with &lt;strong&gt;extreme spikes&lt;/strong&gt;; Android &lt;strong&gt;always crashed&lt;/strong&gt; on this fixture.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://github.com/ifeoluwak/react-native-fast-json/tree/main/example" rel="noopener noreferrer"&gt;example app&lt;/a&gt; implements download + &lt;code&gt;parseFile&lt;/code&gt; + timing UI, use it as a starting point, not as universal truth.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Idea&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;JSON.parse&lt;/code&gt; &lt;strong&gt;materializes&lt;/strong&gt; the whole document in the JS heap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Technique&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Parse in &lt;strong&gt;native&lt;/strong&gt; with simdjson; expose &lt;strong&gt;&lt;code&gt;JsonView&lt;/code&gt;&lt;/strong&gt;; read &lt;strong&gt;lazily&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;data_250mb.json&lt;/code&gt;:&lt;/strong&gt; ~&lt;strong&gt;100 ms&lt;/strong&gt; (iOS) / ~&lt;strong&gt;500 ms&lt;/strong&gt; (Android) for &lt;code&gt;parseFile&lt;/code&gt; in our tests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CPU / memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Stable&lt;/strong&gt; on native parse; &lt;code&gt;JSON.parse&lt;/code&gt; had &lt;strong&gt;extreme spikes&lt;/strong&gt; on iOS and &lt;strong&gt;crashed&lt;/strong&gt; on Android for this fixture.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Avoid blowing up the &lt;strong&gt;JS heap&lt;/strong&gt;; native still holds &lt;strong&gt;~file size&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discipline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;release(path)&lt;/code&gt;, avoid huge &lt;code&gt;asObject()&lt;/code&gt; / &lt;code&gt;rawJson()&lt;/code&gt;, extract scalars to plain JS when done.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Try react-native-fast-json
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add react-native-fast-json react-native-nitro-modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install pods, rebuild, then use &lt;code&gt;fastJson.parseFile&lt;/code&gt; for large files on disk. Peer dependency: &lt;strong&gt;&lt;a href="https://nitro.margelo.com/" rel="noopener noreferrer"&gt;react-native-nitro-modules&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>json</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Yoga: A Simple Guide to Layout in React Native</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Sat, 02 May 2026 10:51:20 +0000</pubDate>
      <link>https://dev.to/running_squirrel/yoga-a-simple-guide-to-layout-in-react-native-48m3</link>
      <guid>https://dev.to/running_squirrel/yoga-a-simple-guide-to-layout-in-react-native-48m3</guid>
      <description>&lt;p&gt;When you build layouts in &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;, you write styles that look a lot like CSS: &lt;code&gt;flexDirection&lt;/code&gt;, &lt;code&gt;alignItems&lt;/code&gt;, &lt;code&gt;justifyContent&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;But here's the interesting part:&lt;/p&gt;

&lt;p&gt;There's no browser.&lt;/p&gt;

&lt;p&gt;So… what's actually calculating your layout?&lt;/p&gt;

&lt;p&gt;That's where &lt;a href="https://yogalayout.com/" rel="noopener noreferrer"&gt;Yoga&lt;/a&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Yoga?
&lt;/h2&gt;

&lt;p&gt;Yoga is an open-source, embeddable, high-performance layout engine that implements a subset of CSS Flexbox (and evolving toward broader web standards).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It calculates the size and position of UI elements ("boxes") based on styles like flex properties, margins, padding, and alignment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Written primarily in C++ (with earlier C implementations), Yoga is not a full UI framework, it does no drawing or rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Your Code (JS)
 ↓
React Native
 ↓
🧠 Yoga (calculates layout)
 ↓
Native Views (iOS / Android)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How Did Yoga Come About?
&lt;/h2&gt;

&lt;p&gt;Early on, &lt;a href="https://www.meta.com/en-gb/about/" rel="noopener noreferrer"&gt;Meta/Facebook&lt;/a&gt; faced a big challenge: building consistent layouts across platforms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;iOS had its own layout system&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Android had a completely different one&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web used CSS and Flexbox&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maintaining separate layout logic for each platform quickly became painful.&lt;/p&gt;

&lt;p&gt;So Meta built &lt;strong&gt;Yoga&lt;/strong&gt;, a layout engine that could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Run on multiple platforms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deliver consistent layout behavior&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be fast enough for mobile apps&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually, they open-sourced it, and it became a core part of React Native.&lt;/p&gt;

&lt;p&gt;Today, Yoga lives at &lt;a href="https://www.yogalayout.dev/" rel="noopener noreferrer"&gt;yogalayout.dev&lt;/a&gt; and continues evolving with contributions from the community and Meta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why React Native Needs Yoga
&lt;/h2&gt;

&lt;p&gt;Unlike web apps, React Native doesn't have access to browser engines like Chrome or Safari.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No built-in Flexbox engine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No CSS layout engine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No DOM&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Native platforms use different layout systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;iOS: Auto Layout (constraints-based) or manual frame setting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Android: Various ViewGroup layouts (LinearLayout, ConstraintLayout, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without a unified system, developers would face platform-specific code, inconsistent behavior, and harder maintenance.&lt;/p&gt;

&lt;p&gt;React Native's promise is "learn once, write anywhere," so layout must feel consistent and declarative.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Consistency for the same layout code to produce identical results across iOS, Android, web (in some contexts), and other platforms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Yoga Solves Layout
&lt;/h2&gt;

&lt;p&gt;Whenever you write styles in React Native, Yoga steps in behind the scenes.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
  &lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;space-between&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Style Translation&lt;/strong&gt;: React Native passes these props to Yoga nodes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layout Calculation&lt;/strong&gt;: Yoga builds a tree of nodes and runs its Flexbox algorithm to compute exact positions and sizes. It handles nesting, wrapping, stretching, shrinking, percentages, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Native Application&lt;/strong&gt;: Results are applied to native views (UIView on iOS, View on Android) for rendering.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What Yoga actually does:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;em&gt;Builds a layout tree&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Parent View
├── Child 1 (50x50)
└── Child 2 (50x50)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; &lt;em&gt;Applies Flexbox rules&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;horizontal&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;

&lt;span class="nx"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;between&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;push&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="nx"&gt;apart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; &lt;em&gt;Calculates positions&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Parent Width = 300 (example)

Child 1 → x: 0 Child 2 → x: 250
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; &lt;em&gt;Then React Native simply renders this using native components.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;|[■]--------------------[■]|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of this happens incredibly fast because Yoga is written in C++ and optimized for performance.&lt;/p&gt;

&lt;p&gt;One important detail:  Yoga doesn't render anything, it only &lt;strong&gt;calculates layout&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Are There Alternatives?
&lt;/h2&gt;

&lt;p&gt;Yoga dominates in React Native, but alternatives and related options exist:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native-only approaches&lt;/strong&gt;: Use platform-specific tools like ConstraintLayout (Android) or Auto Layout/SwiftUI (iOS). These require more conditional code and lose the "write once" benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other Flexbox engines&lt;/strong&gt;: Older css-layout (Yoga's predecessor) or community ports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emerging alternatives&lt;/strong&gt;: Libraries like Taffy (Rust-based, supports more CSS features like Grid and calc) are discussed in other UI contexts as potential future options, though not integrated into React Native.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web-based&lt;/strong&gt;: For React Native Web, it aligns with browser Flexbox/Grid, but Yoga handles the native side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom or third-party&lt;/strong&gt;: Some apps mix Yoga with manual native layout for performance-critical sections, or use libraries like Reanimated for animated layout changes on top of Yoga.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Yoga is one of those tools you rarely think about, but rely on constantly.&lt;/p&gt;

&lt;p&gt;It quietly powers every layout in React Native, translating simple style rules into precise, performant UI across platforms.&lt;/p&gt;

&lt;p&gt;Next time you align a few views with &lt;code&gt;justifyContent&lt;/code&gt;, take a moment to appreciate the sophisticated engine working behind the scenes, doing Yoga, so you don't have to.&lt;/p&gt;

&lt;p&gt;For deeper dives, check the official docs at &lt;a href="https://www.yogalayout.dev/" rel="noopener noreferrer"&gt;yogalayout.dev&lt;/a&gt; or experiment in a React Native project. Happy coding!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>android</category>
      <category>ios</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Offline React Native Apps: How to Cache Files That Must Open Without Network</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Sat, 25 Apr 2026 09:41:36 +0000</pubDate>
      <link>https://dev.to/running_squirrel/offline-react-native-apps-how-to-cache-files-that-must-open-without-network-1ahn</link>
      <guid>https://dev.to/running_squirrel/offline-react-native-apps-how-to-cache-files-that-must-open-without-network-1ahn</guid>
      <description>&lt;p&gt;If you search for “offline React Native,” you will find a lot of guidance about images, lists, and optimistic UI. That is useful, but it often misses the assets that actually stop work in the field: &lt;strong&gt;PDFs, JSON manifests, small binaries, audio clips&lt;/strong&gt;, and other HTTP-hosted files your app must open &lt;em&gt;right now&lt;/em&gt;, even when connectivity is unreliable.&lt;/p&gt;

&lt;p&gt;One of the best libraries for that specific “cache downloads to disk, open them later” capability is &lt;a href="https://github.com/ifeoluwak/react-native-nitro-cache" rel="noopener noreferrer"&gt;&lt;code&gt;react-native-nitro-cache&lt;/code&gt;&lt;/a&gt; with it's simplistic api anyone can use easily.&lt;/p&gt;

&lt;p&gt;This post is about that second category: file caching for offline-capable React Native apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why “offline React Native” advice often skips the hard part
&lt;/h2&gt;

&lt;p&gt;Most offline guidance optimizes what users &lt;em&gt;see immediately&lt;/em&gt;: scrolling, perceived speed, optimistic updates. That matters, but field workflows also depend on what users can &lt;em&gt;open from storage&lt;/em&gt; when the network disappears.&lt;/p&gt;

&lt;p&gt;Operational apps tend to fail for file reasons, not layout reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;PDF checklist&lt;/strong&gt; did not download before the technician walked into a basement&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;rules manifest&lt;/strong&gt; is stale after a midnight policy change&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;small binary&lt;/strong&gt; or &lt;strong&gt;audio instruction&lt;/strong&gt; is missing when the user is already offline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What you want in those situations is not a prettier loading state. You want a &lt;strong&gt;predictable HTTP file cache&lt;/strong&gt; with explicit freshness and cleanup tools.&lt;/p&gt;

&lt;p&gt;That is the shape of problem a file cache is meant to solve: downloads you can treat as &lt;strong&gt;local files&lt;/strong&gt;, with &lt;strong&gt;TTL&lt;/strong&gt;, &lt;strong&gt;forced refresh&lt;/strong&gt;, and simple ways to &lt;strong&gt;inspect and clean up&lt;/strong&gt; what is on disk—so your app can open operational assets offline, not only render UI faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The offline-first file workflow
&lt;/h2&gt;

&lt;p&gt;Think in layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prefetch the critical path&lt;/strong&gt; while the user still has good connectivity (login, sync screen, “prepare for today” action).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serve from disk&lt;/strong&gt; during the session using stable local file paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revalidate on a schedule&lt;/strong&gt; using TTLs that match how often each asset class changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Force refresh&lt;/strong&gt; when the server says “this version is invalid” (feature flags, emergency policy updates).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe and prune&lt;/strong&gt; using cache stats/entries so support and QA can reason about what is on-device.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This maps cleanly to the &lt;a href="https://github.com/ifeoluwak/react-native-nitro-cache" rel="noopener noreferrer"&gt;&lt;code&gt;react-native-nitro-cache&lt;/code&gt;&lt;/a&gt; primitives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getOrFetch(url, options?)&lt;/code&gt; — return a valid cached file or download it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get(url)&lt;/code&gt; — read-through without downloading&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;has(url)&lt;/code&gt; — fast synchronous membership check against the in-memory index&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getBuffer(url)&lt;/code&gt; — read bytes into an &lt;code&gt;ArrayBuffer&lt;/code&gt; for small in-memory consumers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;remove(url)&lt;/code&gt; / &lt;code&gt;clear()&lt;/code&gt; — targeted invalidation vs nuclear reset&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getStats()&lt;/code&gt; / &lt;code&gt;getEntries()&lt;/code&gt; — operational visibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example: different TTLs for different file classes
&lt;/h2&gt;

&lt;p&gt;In real apps, “freshness” is not one number. Treat manifests, templates, and media differently.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rnNitroCache&lt;/span&gt; &lt;span class="p"&gt;}&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-nitro-cache&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cacheManifest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="c1"&gt;// Changes frequently: short TTL 10mins&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rnNitroCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cachePdfTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="c1"&gt;// Changes rarely: longer TTL 7days&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rnNitroCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;7&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;p&gt;When an entry is returned, you typically care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;url&lt;/code&gt;&lt;/strong&gt;: absolute on-disk path you can hand to viewers/players&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;contentType&lt;/code&gt;&lt;/strong&gt;: useful for routing and validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;size&lt;/code&gt;&lt;/strong&gt;: useful for UI and telemetry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;expiresAt&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;0&lt;/code&gt; if the entry has no TTL; otherwise the expiry instant in &lt;strong&gt;milliseconds since epoch&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example: parse cached JSON without inventing a parallel storage system
&lt;/h2&gt;

&lt;p&gt;For small JSON blobs, &lt;code&gt;getBuffer&lt;/code&gt; can be convenient if your consumer wants bytes in JS.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rnNitroCache&lt;/span&gt; &lt;span class="p"&gt;}&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-nitro-cache&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readCachedJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buf&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;rnNitroCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;buf&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buf&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;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;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;h2&gt;
  
  
  Invalidation that matches real product events
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Offline support is not only “store more.” It is also “remove the right things at the right time.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Common triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User logs out&lt;/strong&gt; → &lt;code&gt;clear()&lt;/code&gt; if your policy requires wiping cached HTTP assets from the device&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tenant/workspace switch&lt;/strong&gt; → &lt;code&gt;clear()&lt;/code&gt; or selective &lt;code&gt;remove(url)&lt;/code&gt; for tenant-scoped URLs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server publishes a new bundle version&lt;/strong&gt; → &lt;code&gt;getOrFetch(url, { forceRefresh: true })&lt;/code&gt; for the entry points that must update immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Observability: treat the cache as part of your release story
&lt;/h2&gt;

&lt;p&gt;If you have ever debugged “it works on Wi‑Fi,” you know the missing ingredient is visibility.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rnNitroCache&lt;/span&gt; &lt;span class="p"&gt;}&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-nitro-cache&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;stats&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;rnNitroCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStats&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cache entries:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;totalEntries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bytes:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;totalSize&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;entries&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;rnNitroCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getEntries&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="p"&gt;})));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is valuable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QA scripts (“did we prefetch the manifest?”)&lt;/li&gt;
&lt;li&gt;internal diagnostics screens&lt;/li&gt;
&lt;li&gt;coarse “disk budget” warnings before downloads&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation and platform reality (so your readers do not get stuck)
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What I would emphasize in a Medium conclusion
&lt;/h2&gt;

&lt;p&gt;Offline React Native is getting more attention because teams are shipping more serious mobile workflows. But it is not just "more caching", it is &lt;strong&gt;the right kind of caching&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;operational files you can open from disk under poor connectivity&lt;/li&gt;
&lt;li&gt;explicit freshness (TTL) and forced refresh paths&lt;/li&gt;
&lt;li&gt;disk-first retrieval for large assets&lt;/li&gt;
&lt;li&gt;targeted invalidation and introspection APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If your roadmap includes offline inspections, offline forms, offline training content, or any “must open on-site” PDFs and manifests, a general-purpose file cache belongs in your architecture review alongside your sync and persistence strategy.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Repo link
&lt;/h2&gt;

&lt;p&gt;To learn more about the library checkout it's repository on &lt;a href="https://github.com/ifeoluwak/react-native-nitro-cache" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>offline</category>
      <category>mobile</category>
      <category>network</category>
    </item>
    <item>
      <title>Top 4 React Native Image Caching Libraries in 2026</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Wed, 22 Apr 2026 20:09:14 +0000</pubDate>
      <link>https://dev.to/running_squirrel/top-4-react-native-image-caching-libraries-in-2026-22n1</link>
      <guid>https://dev.to/running_squirrel/top-4-react-native-image-caching-libraries-in-2026-22n1</guid>
      <description>&lt;p&gt;An opinionated guide to image caching in React Native, from battle-tested classics to the blazing-fast newcomer built for the New Architecture.&lt;/p&gt;

&lt;p&gt;Caching images in React Native has always been painful. The default &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt; component is slow, flickers on reloads, and offers almost zero control.&lt;br&gt;
For years developers have relied on a handful of libraries but most of them were built before the New Architecture, before Turbo Modules or Nitro Modules, and before apps started demanding smooth video caching and zero-copy performance.&lt;/p&gt;

&lt;p&gt;In 2026, the game has changed. Here are the Top 4 image caching libraries I recommend today, ranked by real-world usage, performance, and developer experience.&lt;br&gt;
Make sure you check out the last one!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/react-native-fast-image" rel="noopener noreferrer"&gt;react-native-fast-image&lt;/a&gt;&lt;/strong&gt; - The Veteran King (Still Dominant)&lt;/p&gt;

&lt;p&gt;The library is no longer actively maintained but still being used by many. I strongly recommend the fork - &lt;a href="https://www.npmjs.com/package/@d11/react-native-fast-image" rel="noopener noreferrer"&gt;@d11/react-native-fast-image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Battle-tested for years&lt;/li&gt;
&lt;li&gt;Excellent image prioritization and cache control&lt;/li&gt;
&lt;li&gt;Huge community&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;New Architecture support is patchy (community fork required)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Higher bridge overhead compared to modern Nitro solutions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still the go-to for many production apps, but it's starting to show its age.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/expo-image" rel="noopener noreferrer"&gt;expo-image&lt;/a&gt;&lt;/strong&gt; - The Expo Ecosystem Favorite&lt;/p&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Beautiful API and great DX&lt;/li&gt;
&lt;li&gt;Excellent New Architecture support&lt;/li&gt;
&lt;li&gt;Built-in memory + disk caching with cachePolicy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tied to the Expo ecosystem (less ideal for bare React Native)&lt;/li&gt;
&lt;li&gt;Limited programmatic control (no easy remove(url) or cache inspection)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect if you're already in Expo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/react-native-turbo-image" rel="noopener noreferrer"&gt;&lt;strong&gt;react-native-turbo-image&lt;/strong&gt;&lt;/a&gt; - The Modern Native Contender&lt;/p&gt;

&lt;p&gt;Built on Nuke (iOS) and Coil (Android), this library delivers excellent native performance and is gaining traction fast.&lt;/p&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very fast native image loading&lt;/li&gt;
&lt;li&gt;Good New Architecture compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller community than fast-image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A strong option if you want native speed without Nitro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/react-native-nitro-cache" rel="noopener noreferrer"&gt;&lt;strong&gt;react-native-nitro-cache&lt;/strong&gt;&lt;/a&gt; - The Newcomer That's Stealing the Show&lt;/p&gt;

&lt;p&gt;This is the one I'm most excited about in 2026.&lt;br&gt;
Built from the ground up with Nitro Modules + C++, react-native-nitro-cache is a unified asset cache for images, videos, and any binary files. Has a very simple api interface, very easy to use.&lt;/p&gt;

&lt;p&gt;Why it stands out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unified caching (images + videos + arbitrary files)&lt;/li&gt;
&lt;li&gt;Zero-copy ArrayBuffer support for raw binary data&lt;/li&gt;
&lt;li&gt;Blazing-fast in-memory retrieval with safe atomic persistence&lt;/li&gt;
&lt;li&gt;Built-in TTL, programmatic remove(url) and cache inspection&lt;/li&gt;
&lt;li&gt;Full New Architecture support out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It feels like someone finally built the cache library we've all been waiting for since the New Architecture landed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;react-native-fast-image&lt;/strong&gt; and &lt;strong&gt;expo-image&lt;/strong&gt; are still solid choices, they are battle tested and the community love them.&lt;/p&gt;

&lt;p&gt;My 2026 recommendation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expo-heavy project → stick with expo-image&lt;/li&gt;
&lt;li&gt;Need maximum battle-tested stability → react-native-fast-image (with the community fork)&lt;/li&gt;
&lt;li&gt;Want the future of unified, high-performance caching → try &lt;a href="https://www.npmjs.com/package/react-native-nitro-cache" rel="noopener noreferrer"&gt;react-native-nitro-cache&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The library is brand new, actively developed, and already solving real pain points that the older solutions never addressed.&lt;br&gt;
Have you tried it yet? Drop a comment below with your current caching setup. I'd love to hear what's working (or not working) for you in 2026.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>react</category>
      <category>performance</category>
    </item>
    <item>
      <title>Why Mobile Apps Deserve Their Own CMS</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Wed, 20 Aug 2025 04:16:50 +0000</pubDate>
      <link>https://dev.to/running_squirrel/why-mobile-apps-deserve-their-own-cms-311f</link>
      <guid>https://dev.to/running_squirrel/why-mobile-apps-deserve-their-own-cms-311f</guid>
      <description>&lt;p&gt;Every website has a CMS. WordPress, Shopify, Contentful — platforms that make content management simple and instant.&lt;br&gt;
But mobile apps? Still waiting days for app store approvals just to fix a typo.&lt;/p&gt;

&lt;p&gt;Why do apps lack the same content management flexibility as websites?&lt;br&gt;
Because app stores were built for static releases, not agile content updates.&lt;/p&gt;

&lt;p&gt;Product managers, marketers, and even compliance teams often need quick updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Change a banner for a flash sale&lt;/li&gt;
&lt;li&gt; Update legal disclaimers&lt;/li&gt;
&lt;li&gt; Fix onboarding text&lt;/li&gt;
&lt;li&gt; Roll out seasonal content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these should require a rebuild.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33j1wnnvilr0m4l0tuxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33j1wnnvilr0m4l0tuxq.png" alt="Resyncbase Visual Editor" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ResyncBase is filling this gap: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built for React Native apps&lt;/li&gt;
&lt;li&gt;Instant content updates&lt;/li&gt;
&lt;li&gt;Live previews on iOS &amp;amp; Android&lt;/li&gt;
&lt;li&gt;Version history &amp;amp; rollback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Benefit Beyond Speed? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empower non-developers to make changes&lt;/li&gt;
&lt;li&gt;Reduce developer distraction&lt;/li&gt;
&lt;li&gt;Keep users happy with bug-free, up-to-date content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just as websites couldn’t scale without CMS platforms, mobile apps can’t stay competitive with app store delays.&lt;br&gt;
It’s time for a CMS for apps.&lt;/p&gt;

&lt;p&gt;Join the ResyncBase waitlist now at &lt;a href="http://www.resyncbase.com" rel="noopener noreferrer"&gt;www.resyncbase.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>saas</category>
      <category>reactnative</category>
      <category>product</category>
      <category>mobile</category>
    </item>
    <item>
      <title>How to Add a Vertical Timeline To your React Native App</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Fri, 07 Mar 2025 07:24:58 +0000</pubDate>
      <link>https://dev.to/running_squirrel/how-to-add-a-vertical-timeline-to-your-react-native-app-5afn</link>
      <guid>https://dev.to/running_squirrel/how-to-add-a-vertical-timeline-to-your-react-native-app-5afn</guid>
      <description>&lt;p&gt;To add a component to show the progress/timeline of a process with different statuses, you can use the library &lt;a href="https://www.npmjs.com/package/react-native-vertical-status-progress" rel="noopener noreferrer"&gt;react-native-vertical-status-progress&lt;/a&gt;. Works with Expo and React Native.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4p0nw6dh8bu0y89sx88v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4p0nw6dh8bu0y89sx88v.jpg" alt="A Timeline of status progress" width="774" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The  component from the library is designed to visually represent the progress of a multi-step process. Each step is represented by a status indicator that can be customized to show whether the step is completed or pending. This component is ideal for workflows, onboarding processes, or any scenario where you need to display progress through a series of steps. It is compatible with both Expo and React Native projects, making it versatile and easy to integrate into your existing applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Accordion Support: Each status can be expanded or collapsed to show more details. This is useful for providing additional information or actions related to each step.
Customizable Content: You can render any component within the accordion, including call-to-action (CTA) buttons, forms, or any other React Native components.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install react-native-vertical-status-progress&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { VerticalStatusProgress } from 'react-native-vertical-status-progress';

const statuses = [
  {
    title: 'Sign Up Complete',
    subtitle: 'You have successfully signed up.',
    status: 'registered',
  },
  {
    title: 'Set up your account',
    subtitle: 'Add your account details to get started.',
    renderContent: (
      &amp;lt;TouchableOpacity&amp;gt;
        &amp;lt;Text&amp;gt;vbireuvgbireubgireuf&amp;lt;/Text&amp;gt;
      &amp;lt;/TouchableOpacity&amp;gt;
    ),
    status: 'setting_up',
  },
  {
    title: 'Account Verification',
    subtitle: 'We are verifying your account.',
    renderContent: (
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;
          We will contact you shortly if we need any additional information.
          Please contact us if you have any questions. Check your email for
          updates.
        &amp;lt;/Text&amp;gt;
        &amp;lt;TouchableOpacity
          style={{
            backgroundColor: colors.ACCENT_BLUE,
            padding: 10,
            borderRadius: 5,
            width: 150,
            alignItems: 'center',
            marginTop: 10,
          }}
        &amp;gt;
          &amp;lt;Text style={{ color: '#fff' }}&amp;gt;Resend Email&amp;lt;/Text&amp;gt;
        &amp;lt;/TouchableOpacity&amp;gt;
      &amp;lt;/View&amp;gt;
    ),
    status: 'verifying',
  },
  {
    title: 'Account Verified',
    subtitle: 'Your account has been verified.',
    status: 'waiting',
  },
  {
    title: 'All Set!',
    subtitle:
      "You're all set up and ready to go. Start using your account now.",
    renderContent: (
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;
          Lorem ipsum dolor sit, amet consectetur adipisicing elit. A ullam
          assumenda obcaecati? Minima libero vitae ducimus, omnis, excepturi
          saepe, doloribus corrupti hic deleniti id iure? Qui consequuntur at
          magnam consequatur!
        &amp;lt;/Text&amp;gt;
      &amp;lt;/View&amp;gt;
    ),
    status: 'ready',
  },
];

const App = () =&amp;gt; {
    return (
        &amp;lt;VerticalStatusProgress statuses={statuses} /&amp;gt;
    );
};

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can customize the appearance of the react-native-vertical-status-progress component by passing in custom styles and render functions. Here are some examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Custom Ball Component&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const renderCustomBall = (label, idx, isPrev, isFuture) =&amp;gt; (
  &amp;lt;View style={{ backgroundColor: isPrev ? 'blue' : 'grey', width: 16, height: 16, alignItems: 'center', justifyContent: 'center', borderRadius: 4 }}&amp;gt;
    &amp;lt;Text style={{ color: 'white', fontSize: 10 }}&amp;gt;{idx}&amp;lt;/Text&amp;gt;
  &amp;lt;/View&amp;gt;
);

&amp;lt;VerticalStatusProgress
  statuses={statuses}
  renderBall={renderCustomBall}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Custom Stick Component&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const renderCustomStick = (label, idx, isPrev, isFuture) =&amp;gt; (
  &amp;lt;View style={{ flex: 1, width: 5, backgroundColor: isPrev ? 'blue' : 'grey' }} /&amp;gt;
);

&amp;lt;VerticalStatusProgress
  statuses={statuses}
  renderStick={renderCustomStick}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Custom Chevron Component&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const renderCustomChevron = (open, index) =&amp;gt; (
  &amp;lt;Text&amp;gt;{open ? '-' : '+'}&amp;lt;/Text&amp;gt;
);

&amp;lt;VerticalStatusProgress
  statuses={statuses}
  renderChevron={renderCustomChevron}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With react-native-vertical-status-progress it becomes very easy to add any timeline for status progress on your app.&lt;/p&gt;

&lt;p&gt;To see more details about customisation, props and example, visit the library page on npm or github.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>typescript</category>
      <category>expojs</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>How to Generate Types from Your Api Responses in Realtime in Typescript</title>
      <dc:creator>running squirrel</dc:creator>
      <pubDate>Wed, 04 Dec 2024 11:16:35 +0000</pubDate>
      <link>https://dev.to/running_squirrel/how-to-generate-types-from-your-api-responses-in-realtime-in-typescript-2m1i</link>
      <guid>https://dev.to/running_squirrel/how-to-generate-types-from-your-api-responses-in-realtime-in-typescript-2m1i</guid>
      <description>&lt;p&gt;I have always felt a bit annoyed whenever I’m working on a project and I have to add types to an api response.&lt;/p&gt;

&lt;p&gt;The process usually goes like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;write a function to fetch data&lt;/li&gt;
&lt;li&gt;call the function on a component or page&lt;/li&gt;
&lt;li&gt;either log the response or inspect the network tab to view the response
&lt;/li&gt;
&lt;li&gt;copy this response, create a new file and paste the response&lt;/li&gt;
&lt;li&gt;start editing the response to create a new type or interface&lt;/li&gt;
&lt;li&gt;import the new type to the function file and set it’s return type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This had been going on for a while and then I thought to find a way to automate it.&lt;/p&gt;

&lt;p&gt;This led to my discovery of a few libraries that can generate types. Unfortunately they were not convenient to work with because they were not generating the types effortlessly and in realtime. They required a lot of manual process as well. I wanted something I could just plug in and be done with and continue with my normal development flow.&lt;/p&gt;

&lt;p&gt;So I decided to build a library that will automate this process for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  realtime-api-types
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2k2x3ujtaxsdj3g9psv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2k2x3ujtaxsdj3g9psv.png" alt="Generation Service running" width="800" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The aim of this library is to take the pain away from trying to add types from your api responses.&lt;/p&gt;

&lt;p&gt;Find out more on: &lt;a href="https://www.npmjs.com/package/realtime-api-types" rel="noopener noreferrer"&gt;npm&lt;/a&gt; or &lt;a href="https://github.com/ifeoluwak/realtime-api-types" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;With this library, as you get responses from an api, it generates the type for you and saves it to your project, in real time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It also imports the new type and sets it as the return type of your api call. How awesome is that!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just import the helper function and start the server. Thats all. You can then go on with your normal development flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;This setup is meant only for development and not for production! You should not deploy this into your production pipeline.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This library was inspired by an old project I stumbled upon, called &lt;a href="https://github.com/jvilk/MakeTypes" rel="noopener noreferrer"&gt;MakeTypes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;To get started, simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;realtime-api-types &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;There are some configs you need to set.  Go to your &lt;code&gt;package.json&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"realtime-api-types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"objectType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typePath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/types"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"apiPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/apis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fetchType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"axios"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shape of the config is:&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;export&lt;/span&gt; &lt;span class="kd"&gt;type&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;objectType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;interface&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;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// whether you want to generate interfaces or types &lt;/span&gt;
  &lt;span class="nl"&gt;fetchType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&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;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// how you fetch data, fetch or axios&lt;/span&gt;
  &lt;span class="nl"&gt;typePath&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;// the path to where you want to save generated types&lt;/span&gt;
  &lt;span class="nl"&gt;apiPath&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;// the path to where your api methods exist&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start Service
&lt;/h3&gt;

&lt;p&gt;To start the type generator service, run: &lt;code&gt;npx realtime-api-types --init&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Sample &amp;amp; Usage
&lt;/h2&gt;

&lt;p&gt;Wrap your apis in an object and wrap the object with &lt;code&gt;typedApiWrapper&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should make your api methods pure, simply return the api call.&lt;/p&gt;

&lt;p&gt;You can use property assignments or methods or both.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that when you're done developing, remove &lt;code&gt;typedApiWrapper&lt;/code&gt; from this file completely.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example &lt;/span&gt;

&lt;span class="c1"&gt;// src/apis/exercise.ts api file&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;typedApiWrapper&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;realtime-api-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&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;axios&lt;/span&gt;&lt;span class="dl"&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;ExerciseApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;typedApiWrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// with fetch, property assignment style&lt;/span&gt;
  &lt;span class="na"&gt;getExercises&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example-api.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="c1"&gt;// with axios, method style&lt;/span&gt;
   &lt;span class="nf"&gt;getExerciseById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://example-api.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// api post method&lt;/span&gt;
  &lt;span class="nf"&gt;postExercise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&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;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://example-api.com`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&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="c1"&gt;// src/App.tsx file&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ExerciseApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getExercises&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;p&gt;With this setup, whenever an api is called at any point in time, the service will intercept and try to generate type from the response.&lt;/p&gt;

&lt;p&gt;When type generation is successful, the example file above would be automatically updated to something like this:&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;// updated exercise.ts api file&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;typedApiWrapper&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;realtime-api-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&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;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GetExercises&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../types/getExercises&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GetExerciseById&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../types/getExerciseById&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PostExercise&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../types/postExercise&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;ExerciseApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;typedApiWrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// with fetch, property assignment style&lt;/span&gt;
  &lt;span class="na"&gt;getExercises&lt;/span&gt;&lt;span class="p"&gt;:&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;GetExercises&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example-api.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="c1"&gt;// with axios, method style&lt;/span&gt;
   &lt;span class="nf"&gt;getExerciseById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetExerciseById&lt;/span&gt; &lt;span class="p"&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;return&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://example-api.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// api post method&lt;/span&gt;
  &lt;span class="nf"&gt;postExercise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PostExercise&lt;/span&gt; &lt;span class="p"&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;return&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://example-api.com`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&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;blockquote&gt;
&lt;p&gt;Note the difference in structure of return type from fetch and axios.&lt;br&gt;
&lt;code&gt;axios&lt;/code&gt; returns a &lt;code&gt;data: Type&lt;/code&gt;. Do not mix axios and fetch in your project, else you'll get wrong types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Naming Convention
&lt;/h2&gt;

&lt;p&gt;Note the naming convention in the example above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The name of the type file is the same as the name of the &lt;strong&gt;api method called&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The name of the type itself is the same as the name of the api method but in &lt;strong&gt;pascal case&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  React Native or Expo
&lt;/h2&gt;

&lt;p&gt;For this to work with React native or Expo, make sure you follow their guide on how to enable api calls to localhost&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cannot generate enums from response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cannot extend type from different type files. If the response from a call contains object that is similar to another type in another file, it cannot extend it. A new type will be generated in the new file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cannot give custom file names or type names. File name and type name is solely based on the name of the api method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once a type has been generated for an api call, the type will not update with new api calls. You need to delete the previous generated type file to generate a new one.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This library only serves to help you get started quickly and reduce time spent adding types to api calls. You might need to make some updates to the generated types sometimes. It does not solve all your type problems.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>api</category>
      <category>automation</category>
      <category>node</category>
    </item>
  </channel>
</rss>
