<?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: Vijesh KR</title>
    <description>The latest articles on DEV Community by Vijesh KR (@vijeshkr).</description>
    <link>https://dev.to/vijeshkr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4132922%2F8cd65d5d-c161-4213-820b-91a1a6ae3775.jpg</url>
      <title>DEV Community: Vijesh KR</title>
      <link>https://dev.to/vijeshkr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vijeshkr"/>
    <language>en</language>
    <item>
      <title>React Native Rendering: Understanding What Happens Between React Code and the Screen</title>
      <dc:creator>Vijesh KR</dc:creator>
      <pubDate>Sun, 27 Sep 2026 07:59:37 +0000</pubDate>
      <link>https://dev.to/vijeshkr/react-native-rendering-understanding-what-happens-between-react-code-and-the-screen-5dm7</link>
      <guid>https://dev.to/vijeshkr/react-native-rendering-understanding-what-happens-between-react-code-and-the-screen-5dm7</guid>
      <description>&lt;p&gt;When I first started using React Native, I understood the code I was writing.&lt;/p&gt;

&lt;p&gt;I knew what this meant:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I knew that &lt;code&gt;View&lt;/code&gt; was something like a container and &lt;code&gt;Text&lt;/code&gt; displayed text.&lt;/p&gt;

&lt;p&gt;But I had never really asked a deeper question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What actually happens between my React code and the pixels I see on the screen?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code looks simple.&lt;/p&gt;

&lt;p&gt;The result looks simple.&lt;/p&gt;

&lt;p&gt;But there is a lot happening in between.&lt;/p&gt;

&lt;p&gt;React Native has to take the React components we write in JavaScript, understand their structure, calculate where everything should appear, figure out what actually changed, and finally update the real native views on Android or iOS.&lt;/p&gt;

&lt;p&gt;This is where concepts like &lt;strong&gt;Reconciliation, Fabric, Shadow Tree, Yoga, Commit, and Mount&lt;/strong&gt; start to make sense.&lt;/p&gt;

&lt;p&gt;Instead of learning these as separate terms, I found it much easier to understand them as different parts of the same journey.&lt;/p&gt;

&lt;p&gt;So let's follow that journey.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fen0vnrpnil4lasjj9y1o.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fen0vnrpnil4lasjj9y1o.png" alt="High-level overview showing React Code → Renderer/Fabric → Shadow Tree → Layout → Commit → Mount → Native UI → Screen. This is the main architecture image." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Code We Write
&lt;/h2&gt;

&lt;p&gt;Let's start with something very simple.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Welcome() {
  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At the React level, this is just a component.&lt;/p&gt;

&lt;p&gt;React sees something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome
   ↓
&amp;lt;View&amp;gt;
   ↓
&amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But Android and iOS don't understand React components.&lt;/p&gt;

&lt;p&gt;Android doesn't have a native component called &lt;code&gt;&amp;lt;View&amp;gt;&lt;/code&gt; in the React sense.&lt;/p&gt;

&lt;p&gt;iOS doesn't know what &lt;code&gt;&amp;lt;Text&amp;gt;&lt;/code&gt; means.&lt;/p&gt;

&lt;p&gt;The operating system understands native UI objects.&lt;/p&gt;

&lt;p&gt;So there is an important gap:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Code
    ↓
    ?
    ↓
Native Views
    ↓
  Pixels
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What happens in that ?&lt;/p&gt;

&lt;p&gt;That is the rendering system.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdfns01ythrwu08prc28n.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdfns01ythrwu08prc28n.png" alt="Visual explanation of the gap between React components like &lt;View&gt; / &lt;Text&gt; and actual Android/iOS native views." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does React Native Need a Rendering System?
&lt;/h2&gt;

&lt;p&gt;If React already knows what the UI should look like, why can't React just directly create the native views?&lt;/p&gt;

&lt;p&gt;Because there is more to rendering a UI than creating views.&lt;/p&gt;

&lt;p&gt;Consider this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View style={{ flex: 1 }}&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before Android or iOS can display this correctly, React Native needs to know things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the parent-child structure?&lt;/li&gt;
&lt;li&gt;What size should the &lt;code&gt;View&lt;/code&gt; have?&lt;/li&gt;
&lt;li&gt;Where should the &lt;code&gt;Text&lt;/code&gt; be positioned?&lt;/li&gt;
&lt;li&gt;How much space is available?&lt;/li&gt;
&lt;li&gt;What happens if the screen size changes?&lt;/li&gt;
&lt;li&gt;What changed if state updates?&lt;/li&gt;
&lt;li&gt;Which native views actually need to be created?&lt;/li&gt;
&lt;li&gt;Which existing views can simply be updated?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;React Native therefore needs an intermediate representation and a rendering process.&lt;/p&gt;

&lt;p&gt;This is one of the most important ideas to understand:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;React describes what the UI should look like. React Native's renderer figures out how that description becomes native UI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And in the New Architecture, that renderer is called &lt;strong&gt;Fabric&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But before getting to Fabric, there is another React concept we need to understand.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reconciliation: What Actually Changed?
&lt;/h2&gt;

&lt;p&gt;Imagine we have a counter.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Counter() {
  const [count, setCount] = useState(0);

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;{count}&amp;lt;/Text&amp;gt;

      &amp;lt;Button
        title="Increase"
        onPress={() =&amp;gt; setCount(count + 1)}
      /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Initially:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After pressing the button:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;React doesn't need to throw away the entire UI and build everything again.&lt;/p&gt;

&lt;p&gt;It needs to understand what changed.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Previous UI

&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;0&amp;lt;/Text&amp;gt;
  &amp;lt;Button /&amp;gt;
&amp;lt;/View&amp;gt;


New UI

&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;1&amp;lt;/Text&amp;gt;
  &amp;lt;Button /&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The structure is mostly the same.&lt;/p&gt;

&lt;p&gt;Only the text changed.&lt;/p&gt;

&lt;p&gt;This process of React determining what the updated UI should look like is part of what we commonly call &lt;strong&gt;reconciliation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The important idea is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A React update does not mean every native view must be recreated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The renderer can compare the previous and next representations and eventually apply only the necessary native changes.&lt;/p&gt;

&lt;p&gt;This becomes especially important when an application becomes large.&lt;/p&gt;

&lt;p&gt;Imagine a screen with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header
Profile
Statistics
Charts
Transactions
Buttons
Footer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If one transaction amount changes, we don't want to rebuild everything.&lt;/p&gt;

&lt;p&gt;We want the renderer to understand the difference.&lt;/p&gt;

&lt;p&gt;This is where Fabric becomes important.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing Fabric
&lt;/h2&gt;

&lt;p&gt;Fabric is React Native's new rendering system.&lt;/p&gt;

&lt;p&gt;It is not a completely separate UI framework.&lt;/p&gt;

&lt;p&gt;It is the rendering system that connects React's world with the native platform.&lt;/p&gt;

&lt;p&gt;The architecture was redesigned around a shared C++ core, better interoperability with native platforms, and capabilities needed for modern React Native.&lt;/p&gt;

&lt;p&gt;A simplified mental model looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Components
       ↓
React Reconciliation
       ↓
   Fabric Renderer
       ↓
    Shadow Tree
       ↓
  Layout Calculation
       ↓
      Commit
       ↓
      Mount
       ↓
      Screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But there is something important hiding inside this diagram.&lt;/p&gt;

&lt;p&gt;Fabric doesn't immediately create native views when React renders.&lt;/p&gt;

&lt;p&gt;Instead, it builds an intermediate representation.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;React Shadow Tree&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Shadow Tree
&lt;/h2&gt;

&lt;p&gt;When I first heard the term "Shadow Tree", I thought it was something complicated.&lt;/p&gt;

&lt;p&gt;The basic idea is actually quite simple.&lt;/p&gt;

&lt;p&gt;Suppose we write:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Conceptually, React has a tree:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;View
 └── Text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Fabric creates a corresponding tree of &lt;strong&gt;Shadow Nodes&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ViewShadowNode
      │
      └── TextShadowNode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A React Shadow Tree is created by Fabric and consists of React Shadow Nodes.&lt;/p&gt;

&lt;p&gt;These nodes represent the React UI and contain information needed by the renderer, including props and layout information.&lt;/p&gt;

&lt;p&gt;So instead of immediately saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Create an Android View."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fabric first builds a structured representation of what needs to exist.&lt;/p&gt;

&lt;p&gt;This gives the renderer a place to reason about the UI before touching the actual native views.&lt;/p&gt;

&lt;p&gt;Think of it like a plan.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Code

&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;

       ↓

Shadow Tree

ViewShadowNode
      │
      └── TextShadowNode

       ↓

Native Views

Android / iOS Views
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This separation is extremely useful.&lt;/p&gt;

&lt;p&gt;Because now React Native can calculate, compare, and prepare changes before applying them to the actual UI.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb4pn59jhxy14zn5dsspc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb4pn59jhxy14zn5dsspc.png" alt="Shows a React component hierarchy becoming ViewShadowNode → TextShadowNode, explaining the intermediate representation used by Fabric." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  But Where Does Layout Come From?
&lt;/h2&gt;

&lt;p&gt;We now know that the Shadow Tree represents the UI.&lt;/p&gt;

&lt;p&gt;But it still doesn't answer an important question.&lt;/p&gt;

&lt;p&gt;Where exactly should each component appear?&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View
  style={{
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  }}
&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;How does React Native decide:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;View:
x = 0
y = 0
width = 390
height = 844

Text:
x = ...
y = ...
width = ...
height = ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is where &lt;strong&gt;Yoga&lt;/strong&gt; comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Yoga and Layout Calculation
&lt;/h2&gt;

&lt;p&gt;React Native uses &lt;strong&gt;Yoga&lt;/strong&gt; as its layout engine for calculating layout information.&lt;/p&gt;

&lt;p&gt;You can think of Yoga as the part responsible for answering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Given these styles and these available constraints, where should everything go?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View
  style={{
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  }}
&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Yoga helps calculate the position and size of the elements.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Available screen
      ↓
Parent constraints
      ↓
    Styles
      ↓
     Yoga
      ↓
x / y / width / height
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The result becomes layout information associated with the Shadow Tree.&lt;/p&gt;

&lt;p&gt;It might conceptually look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;View
x: 0
y: 0
width: 390
height: 844

   └── Text
       x: 160
       y: 400
       width: 70
       height: 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The exact values obviously depend on the device and content.&lt;/p&gt;

&lt;p&gt;The important part is the responsibility.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yoga calculates layout. Fabric uses that layout information as part of turning the Shadow Tree into native UI.&lt;/p&gt;
&lt;/blockquote&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fubsxm9fc3oe8b0vrs39f.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fubsxm9fc3oe8b0vrs39f.png" alt="Shows how styles, constraints, and the component tree go through Yoga to produce x, y, width, and height." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Render, Commit, Mount
&lt;/h2&gt;

&lt;p&gt;At this point, we have enough context to understand the three words that appear again and again in React Native's rendering architecture:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Render.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mount.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are not three unrelated concepts.&lt;/p&gt;

&lt;p&gt;They are three phases of the rendering pipeline.&lt;/p&gt;

&lt;p&gt;React Native's rendering pipeline can be understood as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Render → Commit → Mount
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's understand each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Render
&lt;/h2&gt;

&lt;p&gt;Suppose we write:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;React executes our application logic and produces the React Element Tree in JavaScript.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Component
      ↓
React Element Tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Fabric then creates the corresponding React Shadow Tree.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Element Tree
      ↓
React Shadow Tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So the Render phase is essentially about constructing the next representation of the UI.&lt;/p&gt;

&lt;p&gt;A simplified mental model is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JavaScript / React
        ↓
  React Elements
        ↓
   Shadow Nodes
        ↓
    Shadow Tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Shadow Tree is immutable.&lt;/p&gt;

&lt;p&gt;That means React Native does not simply mutate the existing tree whenever something changes.&lt;/p&gt;

&lt;p&gt;Instead, it creates a new version of the tree, while using structural sharing so unchanged portions don't need to be duplicated unnecessarily.&lt;/p&gt;

&lt;p&gt;That sounds complicated, but the reason is important.&lt;/p&gt;

&lt;p&gt;It makes the rendering system easier to reason about and allows different versions of UI state to be handled safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Commit
&lt;/h2&gt;

&lt;p&gt;Once the new Shadow Tree has been created, React Native needs to prepare it for mounting.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;Commit&lt;/strong&gt; phase.&lt;/p&gt;

&lt;p&gt;Two important things happen here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Layout calculation&lt;/li&gt;
&lt;li&gt;Preparing the next tree for mounting&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yoga calculates the layout of the Shadow Tree using the available constraints and styles.&lt;/p&gt;

&lt;p&gt;Then the newly prepared tree becomes the next tree that can be mounted.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shadow Tree
     ↓
    Yoga
     ↓
Layout information
     ↓
  Next Tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So after Commit, React Native has something much closer to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is the UI tree we want to display, and this is where everything should be."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But we still haven't actually updated the native views.&lt;/p&gt;

&lt;p&gt;That happens next.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Mount
&lt;/h2&gt;

&lt;p&gt;Now we finally reach the native UI.&lt;/p&gt;

&lt;p&gt;The Mount phase takes the Shadow Tree, including its calculated layout, and turns it into the native Host View Tree.&lt;/p&gt;

&lt;p&gt;This is where actual native views are created, updated, removed, or rearranged.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shadow Node
     ↓
Native View
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For Android, this can result in native Android views.&lt;/p&gt;

&lt;p&gt;For iOS, corresponding UIKit views are used.&lt;/p&gt;

&lt;p&gt;The renderer also compares the previously rendered tree with the next tree and produces the required mutations.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Previous Tree
      +
  Next Tree
      ↓
   Tree Diff
      ↓
create / update / remove
      ↓
  Native Views
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Native Views
      ↓
    Screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fznd11ivjtlphztqpcuip.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fznd11ivjtlphztqpcuip.png" alt="Focused diagram explaining the three major phases: Render → Commit → Mount, with what each phase does." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Following One Example From Start to Finish
&lt;/h2&gt;

&lt;p&gt;Let's put everything together.&lt;/p&gt;

&lt;p&gt;Suppose we have:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Greeting() {
  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What happens?&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — React
&lt;/h3&gt;

&lt;p&gt;React executes the component.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Greeting
   ↓
&amp;lt;View&amp;gt;
   ↓
&amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;React creates the React Element Tree.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2 — Fabric
&lt;/h3&gt;

&lt;p&gt;Fabric creates the corresponding Shadow Tree.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ViewShadowNode
      │
      └── TextShadowNode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  Step 3 — Layout
&lt;/h3&gt;

&lt;p&gt;Yoga calculates the layout.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;View
 ├── x
 ├── y
 ├── width
 └── height

Text
 ├── x
 ├── y
 ├── width
 └── height
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  Step 4 — Commit
&lt;/h3&gt;

&lt;p&gt;The newly prepared tree becomes the next tree to be mounted.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5 — Mount
&lt;/h3&gt;

&lt;p&gt;The renderer determines the required native operations.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create View
Create Text
Set Text = "Hello"
Add Text to View
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  Step 6 — Screen
&lt;/h3&gt;

&lt;p&gt;The native platform displays the result.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That's the entire journey.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Component
      ↓
React Element Tree
      ↓
Reconciliation
      ↓
Shadow Tree
      ↓
Yoga Layout
      ↓
Commit
      ↓
Mount
      ↓
Native Views
      ↓
    Screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdn0t0kjke827j3ewrud.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdn0t0kjke827j3ewrud.png" alt="Follows one &lt;View&gt;&lt;Text&gt;Hello&lt;/Text&gt;&lt;/View&gt; example from React component → Element Tree → Shadow Tree → Yoga → Commit → Mount → Native View → Screen." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When State Changes?
&lt;/h2&gt;

&lt;p&gt;The initial render is only half the story.&lt;/p&gt;

&lt;p&gt;The more interesting case is an update.&lt;/p&gt;

&lt;p&gt;Consider:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Counter() {
  const [count, setCount] = useState(0);

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;{count}&amp;lt;/Text&amp;gt;

      &amp;lt;Button
        title="Increase"
        onPress={() =&amp;gt; setCount(count + 1)}
      /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Initially:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The user taps the button.&lt;/p&gt;

&lt;p&gt;Now:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What happens?&lt;/p&gt;




&lt;h2&gt;
  
  
  First: React Updates
&lt;/h2&gt;

&lt;p&gt;The state changes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;count: 0
      ↓
count: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;React produces a new version of the React Element Tree.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Previous

&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;0&amp;lt;/Text&amp;gt;
  &amp;lt;Button /&amp;gt;
&amp;lt;/View&amp;gt;


Next

&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;1&amp;lt;/Text&amp;gt;
  &amp;lt;Button /&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The important thing is that React doesn't need to recreate everything conceptually from scratch.&lt;/p&gt;

&lt;p&gt;The unchanged parts can be shared between the old and new trees.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then: Shadow Tree Update
&lt;/h2&gt;

&lt;p&gt;Fabric creates the updated Shadow Tree.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Old Shadow Tree

View
 ├── Text("0")
 └── Button


New Shadow Tree

View
 ├── Text("1")
 └── Button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice something.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;View&lt;/code&gt; didn't disappear.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Button&lt;/code&gt; didn't disappear.&lt;/p&gt;

&lt;p&gt;The important change is the text.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then: Commit
&lt;/h2&gt;

&lt;p&gt;Yoga/layout work happens as needed.&lt;/p&gt;

&lt;p&gt;The new tree becomes the next tree.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finally: Mount
&lt;/h2&gt;

&lt;p&gt;The renderer compares the previous rendered tree and the new tree.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Previous
   ↓
Text = "0"

Next
   ↓
Text = "1"

Diff
   ↓
Update Text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So the native UI can perform a small update rather than rebuilding the entire screen.&lt;/p&gt;

&lt;p&gt;This is one of the most important ideas to remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;React re-rendering does not mean the entire native UI is recreated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The renderer determines what native mutations are actually necessary.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsaiiarf8cs5frw9wvmh3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsaiiarf8cs5frw9wvmh3.png" alt="Shows count: 0 → count: 1, then the old/new trees, diff, and finally only the required native update." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Can Performance Problems Appear?
&lt;/h2&gt;

&lt;p&gt;Understanding the rendering pipeline changes how I think about React Native performance.&lt;/p&gt;

&lt;p&gt;Before learning this, it is easy to think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"React Native performance means making JavaScript faster."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that is only one part of the story.&lt;/p&gt;

&lt;p&gt;There are multiple places where work can become expensive.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Too Much JavaScript Work
&lt;/h2&gt;

&lt;p&gt;If your component logic is expensive, React may take longer to produce the next UI representation.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Large computation
     ↓
Slow render
     ↓
Delayed UI update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is why things like unnecessary calculations, unnecessary component updates, and poorly structured state can matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Too Much UI
&lt;/h2&gt;

&lt;p&gt;Imagine rendering hundreds or thousands of complex components.&lt;/p&gt;

&lt;p&gt;Even if your JavaScript is reasonable, the renderer still has more UI to reason about.&lt;/p&gt;

&lt;p&gt;Large lists are a classic example.&lt;/p&gt;

&lt;p&gt;This is why list virtualization and careful component design matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Complex Layout
&lt;/h2&gt;

&lt;p&gt;A complicated UI can require significant layout calculation.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nested containers
      ↓
Many layout constraints
      ↓
   More work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Yoga is efficient, but it still has work to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Too Many Native Mutations
&lt;/h2&gt;

&lt;p&gt;Eventually, changes have to reach native views.&lt;/p&gt;

&lt;p&gt;If an update causes a large number of native operations:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createView
updateView
removeView
insertView
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;that work can become expensive.&lt;/p&gt;

&lt;p&gt;So performance isn't just about:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How fast is my JavaScript?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is also about:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How much work is required across the entire rendering pipeline?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Old Architecture vs The New Architecture
&lt;/h2&gt;

&lt;p&gt;This is where many React Native discussions become confusing.&lt;/p&gt;

&lt;p&gt;People often say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Old Architecture was Bridge and New Architecture is Fabric."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's useful as a starting point, but it isn't the complete picture.&lt;/p&gt;

&lt;p&gt;The New Architecture changed several major pieces of React Native's internals.&lt;/p&gt;

&lt;p&gt;In the old architecture, React Native relied heavily on an asynchronous Bridge to serialize and enqueue communication between JavaScript and native code.&lt;/p&gt;

&lt;p&gt;The New Architecture removes that dependency and introduces a new renderer, new native module/component systems, and better support for modern React capabilities.&lt;/p&gt;

&lt;p&gt;A simplified comparison looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Legacy Architecture&lt;/th&gt;
&lt;th&gt;New Architecture&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Renderer&lt;/td&gt;
&lt;td&gt;Legacy renderer&lt;/td&gt;
&lt;td&gt;Fabric&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS ↔ Native communication&lt;/td&gt;
&lt;td&gt;Asynchronous Bridge&lt;/td&gt;
&lt;td&gt;JSI-based interoperability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering model&lt;/td&gt;
&lt;td&gt;Legacy rendering model&lt;/td&gt;
&lt;td&gt;Modern renderer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native modules&lt;/td&gt;
&lt;td&gt;Legacy Native Modules&lt;/td&gt;
&lt;td&gt;New Native Module system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native components&lt;/td&gt;
&lt;td&gt;Legacy system&lt;/td&gt;
&lt;td&gt;New Native Component system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React capabilities&lt;/td&gt;
&lt;td&gt;More limited by architecture&lt;/td&gt;
&lt;td&gt;Better support for modern React features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core rendering logic&lt;/td&gt;
&lt;td&gt;More platform-specific&lt;/td&gt;
&lt;td&gt;More shared C++ logic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Starting with React Native 0.76, the New Architecture became enabled by default and was declared ready for production use.&lt;/p&gt;

&lt;p&gt;But there is an important detail.&lt;/p&gt;

&lt;p&gt;The New Architecture is not a magic switch that automatically makes every application fast.&lt;/p&gt;

&lt;p&gt;Your application can still have:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bad state management
      ↓
Unnecessary renders
      ↓
Heavy computations
      ↓
Huge lists
      ↓
Expensive UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Changing the architecture does not remove application-level bottlenecks.&lt;/p&gt;

&lt;p&gt;The architecture gives React Native better foundations and capabilities.&lt;/p&gt;

&lt;p&gt;We still have to build our applications carefully.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4glp84tg88ki4fcm27n6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4glp84tg88ki4fcm27n6.png" alt="Side-by-side comparison of Legacy Architecture / Bridge and New Architecture / Fabric / JSI, focusing on architectural differences rather than simply labeling one as " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What About Threads?
&lt;/h2&gt;

&lt;p&gt;This is another area where React Native rendering can become confusing.&lt;/p&gt;

&lt;p&gt;You may hear things like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JavaScript Thread
UI Thread
Background Thread
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And then try to memorize:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Render always happens here, Commit always happens there, Mount always happens there."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is not a good mental model.&lt;/p&gt;

&lt;p&gt;The actual implementation and scheduling can vary.&lt;/p&gt;

&lt;p&gt;React Native's rendering architecture involves JavaScript and C++ work, layout/commit work, and native UI work, with scheduling depending on the situation and platform.&lt;/p&gt;

&lt;p&gt;So instead of memorizing:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Render = Thread X
Commit = Thread Y
Mount = Thread Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I prefer to remember the responsibility:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Render
→ What should the UI tree look like?

Commit
→ Prepare the next tree and calculate its layout.

Mount
→ Apply the necessary changes to native UI.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That mental model survives implementation details much better.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does the Shadow Tree Matter?
&lt;/h2&gt;

&lt;p&gt;At this point, we can understand why the Shadow Tree exists.&lt;/p&gt;

&lt;p&gt;Without an intermediate representation, the renderer would have to reason directly about platform-specific native views.&lt;/p&gt;

&lt;p&gt;Instead, Fabric can work with a platform-independent representation:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React
  ↓
Shadow Tree
  ↓
Layout
  ↓
Diff
  ↓
Native Views
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This creates an important separation.&lt;/p&gt;

&lt;p&gt;React doesn't need to know whether the final platform is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Android
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iOS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The renderer and host platform implementation handle that part.&lt;/p&gt;

&lt;p&gt;This is also one reason Fabric's shared C++ core is important.&lt;/p&gt;

&lt;p&gt;More rendering logic can be shared across platforms instead of being duplicated in completely separate implementations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does Mounting Use a Diff?
&lt;/h2&gt;

&lt;p&gt;Imagine an application with this UI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Screen
 ├── Header
 ├── Profile
 ├── Transactions
 │    ├── Transaction 1
 │    ├── Transaction 2
 │    └── Transaction 3
 └── Footer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now imagine one transaction changes.&lt;/p&gt;

&lt;p&gt;We don't want to blindly do:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Delete everything
Create everything again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Previous Tree
      +
  Next Tree
      ↓
   Compare
      ↓
  Find changes
      ↓
Apply mutations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Maybe the result is simply:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update Transaction 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Mount phase turns the difference between trees into the required native mutations.&lt;/p&gt;

&lt;p&gt;This is one of the places where the architecture connects directly to something we care about as developers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;efficient UI updates.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Complete Mental Model
&lt;/h2&gt;

&lt;p&gt;Let's zoom out.&lt;/p&gt;

&lt;p&gt;We started with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But now we can see the bigger picture.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Code
     │
     ▼
React Element Tree
     │
     ▼
Reconciliation
     │
     ▼
Fabric Renderer
     │
     ▼
Shadow Tree
     │
     ▼
Yoga Layout
     │
     ▼
   Commit
     │
     ▼
Previous Tree + Next Tree
     │
     ▼
    Diff
     │
     ▼
   Mount
     │
     ▼
Native Views
     │
     ▼
   Screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnlt6vmxft2elqhet1asv.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnlt6vmxft2elqhet1asv.png" alt="The Final Mental Model — A visual summary of the complete React Native rendering pipeline, showing how React Code → Reconciliation → Fabric → Shadow Tree → Yoga → Commit → Mount → Native UI → Screen fits into the three core phases: Render → Commit → Mount." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the three phases can be remembered very simply:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RENDER

"What should the UI look like?"

COMMIT

"Prepare the next tree and calculate its layout."

MOUNT

"Apply the necessary changes to native UI."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;When I first started working with React Native, I mostly thought about components.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View /&amp;gt;
&amp;lt;Text /&amp;gt;
&amp;lt;FlatList /&amp;gt;
&amp;lt;Pressable /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I learned about state.&lt;/p&gt;

&lt;p&gt;Then performance.&lt;/p&gt;

&lt;p&gt;Then architecture.&lt;/p&gt;

&lt;p&gt;But understanding the rendering pipeline added another layer to the picture.&lt;/p&gt;

&lt;p&gt;A React Native application is not simply:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JavaScript → Screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There is a rendering system between those two worlds.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JavaScript
    ↓
  React
    ↓
  Fabric
    ↓
Shadow Tree
    ↓
  Layout
    ↓
  Commit
    ↓
  Mount
    ↓
Native UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And suddenly terms that initially sounded unrelated start to connect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reconciliation&lt;/strong&gt; helps determine the new React result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fabric&lt;/strong&gt; is the rendering system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shadow Tree&lt;/strong&gt; represents the UI before it becomes native views.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yoga&lt;/strong&gt; calculates layout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt; prepares the next tree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mount&lt;/strong&gt; applies the necessary changes to the native UI.&lt;/p&gt;

&lt;p&gt;These aren't separate topics.&lt;/p&gt;

&lt;p&gt;They are different parts of one process.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Simple Way to Remember It
&lt;/h2&gt;

&lt;p&gt;If I had to explain the entire rendering system in an interview without going too deep into implementation details, I would say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"React Native takes the React component tree produced by JavaScript and uses its renderer, Fabric, to build a Shadow Tree. During the render phase, React and the renderer create the next UI representation. During commit, layout is calculated using Yoga and the new tree is prepared. During mount, React Native diffs the trees and applies the required mutations to the native views."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That explanation is much more useful than memorizing a list of terms.&lt;/p&gt;

&lt;p&gt;Because now every term has a responsibility.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React
→ describes the UI

Reconciliation
→ determines the new React result

Fabric
→ rendering system

Shadow Tree
→ intermediate representation

Yoga
→ layout calculation

Commit
→ prepare the next tree

Mount
→ update native UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The interesting part of React Native is that the code we write is often much simpler than the system executing it.&lt;/p&gt;

&lt;p&gt;When we write:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View&amp;gt;
  &amp;lt;Text&amp;gt;Hello&amp;lt;/Text&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;we don't normally need to think about:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Element Tree
Shadow Nodes
Shadow Tree
Yoga
Commit
Tree Diffing
Mount
Native Views
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And that's exactly what a good abstraction should do.&lt;/p&gt;

&lt;p&gt;We can build applications without understanding every internal detail.&lt;/p&gt;

&lt;p&gt;But when we start working on performance, debugging difficult rendering problems, building native components, or simply trying to understand why React Native works the way it does, these concepts become extremely useful.&lt;/p&gt;

&lt;p&gt;For me, the biggest takeaway is not memorizing the names.&lt;/p&gt;

&lt;p&gt;It is understanding the journey:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;React describes the UI. Fabric builds a representation of that UI. Yoga calculates its layout. Commit prepares the next tree. Mount turns the result into native UI.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once that mental model is clear, React Native rendering stops feeling like a collection of mysterious internal terms.&lt;/p&gt;

&lt;p&gt;It becomes one connected system.&lt;/p&gt;

&lt;p&gt;And that is the part worth remembering.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>mobile</category>
      <category>javascript</category>
    </item>
    <item>
      <title>MVVM and Clean Architecture: Understanding Where Our Code Actually Belongs</title>
      <dc:creator>Vijesh KR</dc:creator>
      <pubDate>Tue, 22 Sep 2026 13:05:44 +0000</pubDate>
      <link>https://dev.to/vijeshkr/mvvm-and-clean-architecture-understanding-where-our-code-actually-belongs-5fnj</link>
      <guid>https://dev.to/vijeshkr/mvvm-and-clean-architecture-understanding-where-our-code-actually-belongs-5fnj</guid>
      <description>&lt;p&gt;When I first started learning software architecture, I thought it was mostly about remembering names:&lt;/p&gt;

&lt;p&gt;MVC.&lt;br&gt;
MVP.&lt;br&gt;
MVVM.&lt;br&gt;
Clean Architecture.&lt;br&gt;
Repository.&lt;br&gt;
Use Case.&lt;br&gt;
Domain.&lt;br&gt;
Data.&lt;/p&gt;

&lt;p&gt;But after working with real applications, I realized that architecture is not really about memorizing these names.&lt;/p&gt;

&lt;p&gt;The more important question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When an application grows, where should each piece of logic actually live?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question is what helped me understand &lt;strong&gt;MVVM&lt;/strong&gt; and &lt;strong&gt;Clean Architecture&lt;/strong&gt; more clearly.&lt;/p&gt;

&lt;p&gt;This article is my attempt to explain both concepts in a practical way, without treating them as complicated rules or a collection of folders.&lt;/p&gt;


&lt;h2&gt;
  
  
  When a Simple Application Starts Becoming Complicated
&lt;/h2&gt;

&lt;p&gt;Imagine we start with a simple expense-tracking application.&lt;/p&gt;

&lt;p&gt;At first, the application might only need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A screen to enter an expense&lt;/li&gt;
&lt;li&gt;A button to save it&lt;/li&gt;
&lt;li&gt;A list showing expenses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything feels simple.&lt;/p&gt;

&lt;p&gt;But then the application grows.&lt;/p&gt;

&lt;p&gt;Now we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input validation&lt;/li&gt;
&lt;li&gt;Different expense categories&lt;/li&gt;
&lt;li&gt;API communication&lt;/li&gt;
&lt;li&gt;Local database storage&lt;/li&gt;
&lt;li&gt;Loading and error states&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Business rules&lt;/li&gt;
&lt;li&gt;Offline support&lt;/li&gt;
&lt;li&gt;Data synchronization&lt;/li&gt;
&lt;li&gt;Reporting&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;Analytics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suddenly, the screen that originally handled a few things is now responsible for many completely different concerns.&lt;/p&gt;

&lt;p&gt;The UI knows about the API.&lt;/p&gt;

&lt;p&gt;The API logic knows about the UI.&lt;/p&gt;

&lt;p&gt;Business rules are mixed with button-click logic.&lt;/p&gt;

&lt;p&gt;Database code appears inside presentation code.&lt;/p&gt;

&lt;p&gt;Changing one thing starts affecting several unrelated parts of the application.&lt;/p&gt;

&lt;p&gt;This is where architecture becomes important.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwpe6ghm91xqxjdk4t6h.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwpe6ghm91xqxjdk4t6h.png" alt="Illustration showing a growing software application becoming complex as UI, business logic, API calls, database operations, state management, and validation become mixed together." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Architecture Is About Responsibility
&lt;/h2&gt;

&lt;p&gt;One of the biggest things I learned is that architecture is not primarily about creating folders.&lt;/p&gt;

&lt;p&gt;You can create folders called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components
services
models
repositories
utils
screens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and still have a badly structured application.&lt;/p&gt;

&lt;p&gt;Architecture is really about &lt;strong&gt;responsibilities and boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every part of the application should have a clear answer to questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is this part responsible for?&lt;/li&gt;
&lt;li&gt;What should it know about?&lt;/li&gt;
&lt;li&gt;What should it not know about?&lt;/li&gt;
&lt;li&gt;Who should it communicate with?&lt;/li&gt;
&lt;li&gt;What happens if the API changes?&lt;/li&gt;
&lt;li&gt;What happens if the database changes?&lt;/li&gt;
&lt;li&gt;Can this business logic be tested without the UI?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once I started looking at architecture this way, MVVM became much easier to understand.&lt;/p&gt;




&lt;h2&gt;
  
  
  MVVM: Separating What We See From What We Do
&lt;/h2&gt;

&lt;p&gt;MVVM stands for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model - View - ViewModel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The basic idea is simple.&lt;/p&gt;

&lt;p&gt;Instead of putting everything inside the UI, we separate the presentation responsibilities.&lt;/p&gt;

&lt;p&gt;Think about a screen that displays a list of expenses.&lt;/p&gt;

&lt;p&gt;The screen needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display the expenses&lt;/li&gt;
&lt;li&gt;Show loading information&lt;/li&gt;
&lt;li&gt;Display errors&lt;/li&gt;
&lt;li&gt;React to user actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But does the screen itself need to know how the data is fetched?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;That is where the ViewModel becomes useful.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslb9nu00g0ulw3a3ccks.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslb9nu00g0ulw3a3ccks.png" alt="Diagram explaining MVVM with three parts: View for the user interface, ViewModel for presentation logic and state, and Model for data." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  View
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;View&lt;/strong&gt; is what the user interacts with.&lt;/p&gt;

&lt;p&gt;Its responsibility is mainly presentation.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screens&lt;/li&gt;
&lt;li&gt;UI components&lt;/li&gt;
&lt;li&gt;Buttons&lt;/li&gt;
&lt;li&gt;Forms&lt;/li&gt;
&lt;li&gt;Lists&lt;/li&gt;
&lt;li&gt;Loading indicators&lt;/li&gt;
&lt;li&gt;Error messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The View should focus on:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What should the user see?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It should not become the place where every application decision is made.&lt;/p&gt;




&lt;h3&gt;
  
  
  ViewModel
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;ViewModel&lt;/strong&gt; sits between the View and the rest of the application.&lt;/p&gt;

&lt;p&gt;It manages things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI state&lt;/li&gt;
&lt;li&gt;User actions&lt;/li&gt;
&lt;li&gt;Presentation logic&lt;/li&gt;
&lt;li&gt;Loading state&lt;/li&gt;
&lt;li&gt;Error state&lt;/li&gt;
&lt;li&gt;Preparing data for the View&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, when a user taps &lt;strong&gt;Save Expense&lt;/strong&gt;, the View does not need to understand everything involved in saving that expense.&lt;/p&gt;

&lt;p&gt;The View can simply communicate the action.&lt;/p&gt;

&lt;p&gt;The ViewModel can then coordinate what needs to happen.&lt;/p&gt;

&lt;p&gt;This gives us a useful separation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;View = What the user sees&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ViewModel = What the UI needs to know and what should happen from a UI action&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Model
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Model&lt;/strong&gt; represents the data and concepts used by the application.&lt;/p&gt;

&lt;p&gt;Depending on how the application is designed, this can include things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data objects&lt;/li&gt;
&lt;li&gt;Entities&lt;/li&gt;
&lt;li&gt;Data structures&lt;/li&gt;
&lt;li&gt;Related data concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact meaning of "Model" can vary between different implementations of MVVM.&lt;/p&gt;

&lt;p&gt;That is important because MVVM itself does not define every detail of the entire application's architecture.&lt;/p&gt;

&lt;p&gt;And this leads to an important point.&lt;/p&gt;




&lt;h2&gt;
  
  
  MVVM Is Not the Entire Architecture
&lt;/h2&gt;

&lt;p&gt;MVVM is mainly a &lt;strong&gt;presentation pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It helps us organize how the UI communicates with presentation logic.&lt;/p&gt;

&lt;p&gt;But what happens after the ViewModel needs to perform an actual business operation?&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Create this expense."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Should the ViewModel directly call the database?&lt;/p&gt;

&lt;p&gt;Should it directly call an API?&lt;/p&gt;

&lt;p&gt;Should it contain all the business rules?&lt;/p&gt;

&lt;p&gt;As applications become larger, putting everything inside the ViewModel can simply create another problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A giant ViewModel.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where a broader architectural approach becomes useful.&lt;/p&gt;

&lt;p&gt;That is where &lt;strong&gt;Clean Architecture&lt;/strong&gt; comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Clean Architecture: Separating the Core From External Details
&lt;/h2&gt;

&lt;p&gt;Clean Architecture is broader than MVVM.&lt;/p&gt;

&lt;p&gt;The main idea is to keep the important business logic of an application independent from external technologies and implementation details.&lt;/p&gt;

&lt;p&gt;External details can include things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI frameworks&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;Network libraries&lt;/li&gt;
&lt;li&gt;Storage systems&lt;/li&gt;
&lt;li&gt;Third-party services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The business logic should not become tightly coupled to these things.&lt;/p&gt;

&lt;p&gt;A common way to understand Clean Architecture is through three major areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presentation&lt;/li&gt;
&lt;li&gt;Domain&lt;/li&gt;
&lt;li&gt;Data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not simply folders.&lt;/p&gt;

&lt;p&gt;They represent different responsibilities and boundaries.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F79v0xex4uq3rpet97udu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F79v0xex4uq3rpet97udu.png" alt="Diagram showing Clean Architecture divided into Presentation, Domain, and Data layers, with business logic at the center and external data sources around it." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Presentation Layer
&lt;/h2&gt;

&lt;p&gt;The Presentation layer is responsible for interacting with the user.&lt;/p&gt;

&lt;p&gt;This is where things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;li&gt;ViewModels&lt;/li&gt;
&lt;li&gt;UI state&lt;/li&gt;
&lt;li&gt;User interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;usually live.&lt;/p&gt;

&lt;p&gt;This is also where MVVM can fit naturally.&lt;/p&gt;

&lt;p&gt;So instead of thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MVVM vs Clean Architecture&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;it is more useful to think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;MVVM can organize the Presentation layer inside a Clean Architecture application.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Domain Layer
&lt;/h2&gt;

&lt;p&gt;The Domain layer is the heart of the application.&lt;/p&gt;

&lt;p&gt;This is where we keep the important business concepts and rules.&lt;/p&gt;

&lt;p&gt;The Domain layer should not need to know whether the application is using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST API&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;A particular UI framework&lt;/li&gt;
&lt;li&gt;A particular network library&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The business rules should remain independent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entities
&lt;/h3&gt;

&lt;p&gt;Entities represent important concepts in the application's business domain.&lt;/p&gt;

&lt;p&gt;For an expense application, an entity might represent an:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expense&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a shopping application:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a banking application:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These concepts exist regardless of which UI framework or database the application uses.&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Use Case&lt;/strong&gt; represents something the application does.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Expense&lt;/li&gt;
&lt;li&gt;Delete Expense&lt;/li&gt;
&lt;li&gt;Create Order&lt;/li&gt;
&lt;li&gt;Cancel Order&lt;/li&gt;
&lt;li&gt;Generate Report&lt;/li&gt;
&lt;li&gt;Update Profile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of thinking about Use Cases as another complicated architectural term, I find it easier to think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A Use Case represents an application action or business operation.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This gives the application a clear place for business logic.&lt;/p&gt;




&lt;h3&gt;
  
  
  Repository Interfaces
&lt;/h3&gt;

&lt;p&gt;The Domain layer may need data, but it should not need to know exactly where that data comes from.&lt;/p&gt;

&lt;p&gt;For example, an &lt;strong&gt;Add Expense&lt;/strong&gt; use case may need to save an expense.&lt;/p&gt;

&lt;p&gt;The Domain layer can depend on an abstraction such as a repository interface.&lt;/p&gt;

&lt;p&gt;It does not need to know whether the repository eventually saves the data to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A remote API&lt;/li&gt;
&lt;li&gt;A local database&lt;/li&gt;
&lt;li&gt;Local storage&lt;/li&gt;
&lt;li&gt;A cache&lt;/li&gt;
&lt;li&gt;Some other data source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That implementation detail belongs outside the Domain layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Data Layer
&lt;/h2&gt;

&lt;p&gt;The Data layer deals with external data sources.&lt;/p&gt;

&lt;p&gt;This can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;Local storage&lt;/li&gt;
&lt;li&gt;Files&lt;/li&gt;
&lt;li&gt;Caches&lt;/li&gt;
&lt;li&gt;Repository implementations&lt;/li&gt;
&lt;li&gt;Data source implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, the Domain layer might say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I need to save an expense."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Data layer handles &lt;strong&gt;how&lt;/strong&gt; that actually happens.&lt;/p&gt;

&lt;p&gt;This separation becomes powerful when external technologies change.&lt;/p&gt;

&lt;p&gt;Suppose an application initially uses one database and later moves to another.&lt;/p&gt;

&lt;p&gt;If the business logic is tightly coupled to the original database, the change can become painful.&lt;/p&gt;

&lt;p&gt;But if the business logic communicates through abstractions, the implementation can change without forcing the business rules to understand the new technology.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Important Idea: Dependency Direction
&lt;/h2&gt;

&lt;p&gt;This is one of the most important ideas behind Clean Architecture.&lt;/p&gt;

&lt;p&gt;It is not enough to separate the application into Presentation, Domain, and Data.&lt;/p&gt;

&lt;p&gt;We also need to think about &lt;strong&gt;which layer depends on which&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The important principle is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The core business logic should not depend directly on external implementation details.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkq2usgppok6k7714ew24.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkq2usgppok6k7714ew24.png" alt="Diagram illustrating Clean Architecture dependency direction, showing external layers depending toward the independent core business logic rather than the core depending on external technologies." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think about a restaurant.&lt;/p&gt;

&lt;p&gt;The customer should not need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which supplier delivered the vegetables&lt;/li&gt;
&lt;li&gt;Which brand of cooking oil was used&lt;/li&gt;
&lt;li&gt;Which kitchen equipment was used&lt;/li&gt;
&lt;li&gt;Where the restaurant purchased its ingredients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The customer cares about the result.&lt;/p&gt;

&lt;p&gt;The restaurant's internal processes can change without changing what the customer expects.&lt;/p&gt;

&lt;p&gt;In a similar way, our business logic should not become tightly connected to external details.&lt;/p&gt;

&lt;p&gt;The database can change.&lt;/p&gt;

&lt;p&gt;The API can change.&lt;/p&gt;

&lt;p&gt;The UI technology can change.&lt;/p&gt;

&lt;p&gt;The core business rules should remain relatively stable.&lt;/p&gt;




&lt;h2&gt;
  
  
  MVVM and Clean Architecture Together
&lt;/h2&gt;

&lt;p&gt;This is where the two concepts finally connect.&lt;/p&gt;

&lt;p&gt;They are not competing architectures.&lt;/p&gt;

&lt;p&gt;They solve problems at different levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MVVM&lt;/strong&gt; helps organize the presentation side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clean Architecture&lt;/strong&gt; helps structure the broader application and control dependencies between different parts.&lt;/p&gt;

&lt;p&gt;A simplified structure can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Presentation
│
├── View
│
└── ViewModel
        │
        ▼
     Domain
        │
        ├── Entities
        ├── Use Cases
        └── Repository Interfaces
                    │
                    ▼
                  Data
                    │
                    ├── Repository Implementations
                    └── Data Sources
                           │
                           ├── API
                           ├── Database
                           └── Local Storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2pq78edbbexdlebnysa.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2pq78edbbexdlebnysa.png" alt="Diagram showing MVVM inside the Presentation layer of Clean Architecture, connecting View and ViewModel with Domain and Data layers." width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
The important thing is not memorizing this diagram.&lt;/p&gt;

&lt;p&gt;The important thing is understanding &lt;strong&gt;why the separation exists&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Following One Action Through the Application
&lt;/h2&gt;

&lt;p&gt;Let's follow a simple example.&lt;/p&gt;

&lt;p&gt;A user wants to add an expense.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. User interacts with the View
&lt;/h3&gt;

&lt;p&gt;The user enters an amount and taps &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The View captures the interaction.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. View communicates with the ViewModel
&lt;/h3&gt;

&lt;p&gt;The ViewModel receives the action.&lt;/p&gt;

&lt;p&gt;It can update UI state, handle presentation concerns, and coordinate the next step.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. ViewModel calls a Use Case
&lt;/h3&gt;

&lt;p&gt;Instead of putting the actual business operation inside the ViewModel, it delegates the operation to the appropriate Use Case.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Expense Use Case&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Use Case applies business rules
&lt;/h3&gt;

&lt;p&gt;The Use Case determines what needs to happen according to the application's rules.&lt;/p&gt;

&lt;p&gt;It may validate the information or coordinate the required operation.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Use Case communicates through a Repository abstraction
&lt;/h3&gt;

&lt;p&gt;The Use Case does not need to know whether the data comes from an API, database, or local storage.&lt;/p&gt;

&lt;p&gt;It communicates through the repository abstraction.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Repository implementation handles the data
&lt;/h3&gt;

&lt;p&gt;The Data layer provides the actual repository implementation.&lt;/p&gt;

&lt;p&gt;That implementation knows how to communicate with the required data source.&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Data Source performs the actual operation
&lt;/h3&gt;

&lt;p&gt;The data may finally reach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An API&lt;/li&gt;
&lt;li&gt;A database&lt;/li&gt;
&lt;li&gt;Local storage&lt;/li&gt;
&lt;li&gt;Another external system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result then travels back through the layers.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkt01e2va9lxtj0jph31v.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkt01e2va9lxtj0jph31v.png" alt="Diagram showing a request flowing from the user and View through ViewModel, Use Case, Repository, and Data Source, with the result returning to the UI" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
  ↓
View
  ↓
ViewModel
  ↓
Use Case
  ↓
Repository Interface
  ↓
Repository Implementation
  ↓
Data Source
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the result comes back in the opposite direction toward the UI.&lt;/p&gt;

&lt;p&gt;This gives every part of the application a clear responsibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Separation Is Useful
&lt;/h2&gt;

&lt;p&gt;The biggest benefit is not simply that the project has more folders.&lt;/p&gt;

&lt;p&gt;The real benefit is that &lt;strong&gt;changes become easier to manage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine the API changes.&lt;/p&gt;

&lt;p&gt;The View should not need to change just because the API response changed.&lt;/p&gt;

&lt;p&gt;Imagine the database changes.&lt;/p&gt;

&lt;p&gt;The business rules should not suddenly need to understand the new database.&lt;/p&gt;

&lt;p&gt;Imagine the UI changes.&lt;/p&gt;

&lt;p&gt;The core business logic should not need to change just because the design changed.&lt;/p&gt;

&lt;p&gt;Imagine we want to test a business rule.&lt;/p&gt;

&lt;p&gt;We should be able to test that rule without launching the entire application.&lt;/p&gt;

&lt;p&gt;This is where good boundaries become valuable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Becomes Easier
&lt;/h2&gt;

&lt;p&gt;Separation also makes testing more focused.&lt;/p&gt;

&lt;p&gt;Instead of testing the entire application every time, different responsibilities can be tested independently.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Can the UI display the correct state?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ViewModel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Does the correct UI state appear after an action?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Does the business rule behave correctly?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Does the data operation work as expected?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Source&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Does the API or database communication work correctly?&lt;/p&gt;

&lt;p&gt;The more independent these responsibilities are, the easier it becomes to identify where a problem actually exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When Technology Changes?
&lt;/h2&gt;

&lt;p&gt;One of the reasons I find Clean Architecture useful is that software technology constantly changes.&lt;/p&gt;

&lt;p&gt;Today we may use one API library.&lt;/p&gt;

&lt;p&gt;Tomorrow we may replace it.&lt;/p&gt;

&lt;p&gt;Today we may use one database.&lt;/p&gt;

&lt;p&gt;Later we may migrate to another.&lt;/p&gt;

&lt;p&gt;The UI framework may change.&lt;/p&gt;

&lt;p&gt;A third-party library may be removed.&lt;/p&gt;

&lt;p&gt;These changes are much easier to handle when our business logic is not directly dependent on every external technology.&lt;/p&gt;

&lt;p&gt;The goal is not to prevent change.&lt;/p&gt;

&lt;p&gt;The goal is to &lt;strong&gt;contain the impact of change&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of Combining MVVM and Clean Architecture
&lt;/h2&gt;

&lt;p&gt;When used appropriately, this combination can provide several benefits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clear separation of responsibilities
&lt;/h3&gt;

&lt;p&gt;Each part of the application has a specific job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better maintainability
&lt;/h3&gt;

&lt;p&gt;Changes can remain localized instead of spreading throughout the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better testability
&lt;/h3&gt;

&lt;p&gt;Business logic can be tested independently from UI and external systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reduced coupling
&lt;/h3&gt;

&lt;p&gt;The core logic does not need to know the implementation details of external technologies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easier scaling
&lt;/h3&gt;

&lt;p&gt;As an application grows, clearly defined boundaries make the codebase easier to understand and extend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easier replacement of technologies
&lt;/h3&gt;

&lt;p&gt;APIs, databases, libraries, and other external tools can potentially be replaced with less impact on the core business logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  But There Is a Trade-Off
&lt;/h2&gt;

&lt;p&gt;Architecture is not free.&lt;/p&gt;

&lt;p&gt;A well-structured architecture usually means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More files&lt;/li&gt;
&lt;li&gt;More abstractions&lt;/li&gt;
&lt;li&gt;More interfaces&lt;/li&gt;
&lt;li&gt;More layers&lt;/li&gt;
&lt;li&gt;More concepts to understand&lt;/li&gt;
&lt;li&gt;More initial setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a very small application, creating a Use Case, Repository Interface, Repository Implementation, Data Source, ViewModel, and several other abstractions for a single screen may be unnecessary.&lt;/p&gt;

&lt;p&gt;That can become &lt;strong&gt;overengineering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal of architecture is not to create the maximum number of layers.&lt;/p&gt;

&lt;p&gt;The goal is to create &lt;strong&gt;useful boundaries for the complexity that actually exists&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A small application may need a simple structure.&lt;/p&gt;

&lt;p&gt;A large application with complicated business rules and multiple data sources may benefit from stronger architectural boundaries.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Is Not About Following a Folder Structure
&lt;/h2&gt;

&lt;p&gt;This is another lesson I find important.&lt;/p&gt;

&lt;p&gt;Someone can create a project like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;presentation/
domain/
data/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and still have poor architecture.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because the folder names themselves do not create separation.&lt;/p&gt;

&lt;p&gt;If the View directly accesses the database, the boundaries are already being broken.&lt;/p&gt;

&lt;p&gt;If the Domain layer directly imports a specific API library, it becomes coupled to that external technology.&lt;/p&gt;

&lt;p&gt;If all the business logic still lives inside one giant ViewModel, simply calling the project "MVVM" does not solve the problem.&lt;/p&gt;

&lt;p&gt;Architecture is about:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Responsibilities.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boundaries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependencies.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Communication between those boundaries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The folder structure is only one way of representing those decisions.&lt;/p&gt;




&lt;h2&gt;
  
  
  MVVM vs Clean Architecture
&lt;/h2&gt;

&lt;p&gt;It becomes much easier to understand the difference when we look at their purpose.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MVVM&lt;/th&gt;
&lt;th&gt;Clean Architecture&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Presentation pattern&lt;/td&gt;
&lt;td&gt;Broader architectural approach&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Focuses mainly on UI and presentation logic&lt;/td&gt;
&lt;td&gt;Focuses on the structure of the whole application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Separates View and ViewModel responsibilities&lt;/td&gt;
&lt;td&gt;Separates application concerns and controls dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Helps organize presentation code&lt;/td&gt;
&lt;td&gt;Helps protect core business logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be used inside Clean Architecture&lt;/td&gt;
&lt;td&gt;Can use MVVM in its Presentation layer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which one should I use?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How can they work together to solve different architectural problems?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A Simple Mental Model
&lt;/h2&gt;

&lt;p&gt;When looking at a piece of code, I try to ask four simple questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does the user see?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;View&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What does the UI need to know or respond to?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ViewModel&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What does the application actually do?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use Case / Domain&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Where does the data come from?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Repository / Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This mental model is much easier to remember than trying to memorize a long list of architectural definitions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;When I started learning architecture, the different terms felt disconnected.&lt;/p&gt;

&lt;p&gt;MVVM felt like one topic.&lt;/p&gt;

&lt;p&gt;Clean Architecture felt like another.&lt;/p&gt;

&lt;p&gt;Repository felt like another.&lt;/p&gt;

&lt;p&gt;Use Cases felt like another.&lt;/p&gt;

&lt;p&gt;But once I started looking at them through responsibilities and dependencies, they started fitting together.&lt;/p&gt;

&lt;p&gt;MVVM helps answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How should presentation logic be organized?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clean Architecture helps answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How should the application be structured so that core logic stays independent from external details?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Repository helps answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How can the application communicate with data without tightly coupling business logic to the data source?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use Cases help answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Where should an application action or business operation live?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Together, these ideas create a much clearer mental model of where code should belong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Good architecture is not about making software complicated.&lt;/p&gt;

&lt;p&gt;It is about making responsibilities clear.&lt;/p&gt;

&lt;p&gt;When an application grows, complexity is inevitable.&lt;/p&gt;

&lt;p&gt;The goal of architecture is not to eliminate complexity completely.&lt;/p&gt;

&lt;p&gt;The goal is to &lt;strong&gt;organize that complexity so that it remains understandable and changeable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;MVVM helps separate what the user sees from the logic that supports the UI.&lt;/p&gt;

&lt;p&gt;Clean Architecture helps separate the core business logic from external implementation details.&lt;/p&gt;

&lt;p&gt;When these ideas are used together thoughtfully, the result is not simply a project with more folders.&lt;/p&gt;

&lt;p&gt;It is a system where:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UI has a responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presentation logic has a responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Business logic has a responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data access has a responsibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And most importantly, the boundaries between them are intentional.&lt;/p&gt;

&lt;p&gt;That, for me, is the real purpose of software architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Not just deciding where code goes, but understanding why it belongs there.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/vijeshkr17q" rel="noopener noreferrer"&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%2F50v0ir9i7iidbb1j190b.png" alt="Buy Me a Coffee" width="545" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>mvvm</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Building a Lightweight Biometric Authentication Library for React Native with Kotlin</title>
      <dc:creator>Vijesh KR</dc:creator>
      <pubDate>Sat, 19 Sep 2026 14:30:22 +0000</pubDate>
      <link>https://dev.to/vijeshkr/building-a-lightweight-biometric-authentication-library-for-react-native-with-kotlin-5al4</link>
      <guid>https://dev.to/vijeshkr/building-a-lightweight-biometric-authentication-library-for-react-native-with-kotlin-5al4</guid>
      <description>&lt;p&gt;Hello developers!&lt;/p&gt;

&lt;p&gt;Today, I want to share a quick story about a common challenge I faced while working with React Native: securing app access with biometric authentication, and why I decided to build and open-source my own library:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;@vijeshkr/react-native-biometric-auth&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Spark: Why Another Biometric Library?
&lt;/h2&gt;

&lt;p&gt;While working on a mobile application that required secure user authentication, such as unlocking the app when it launches, I came across a few challenges with existing solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clunky Fallback Support
&lt;/h3&gt;

&lt;p&gt;Handling fallback authentication can sometimes require additional configuration.&lt;/p&gt;

&lt;p&gt;I wanted a solution where users could authenticate using biometrics while also having the option to fall back to their device credentials, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fingerprint&lt;/li&gt;
&lt;li&gt;Device PIN&lt;/li&gt;
&lt;li&gt;Pattern&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Legacy Native Dependencies
&lt;/h3&gt;

&lt;p&gt;I also wanted to avoid relying on older Java-based implementations and instead use modern Android APIs with &lt;strong&gt;Kotlin&lt;/strong&gt; and &lt;strong&gt;AndroidX Biometric&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Keeping Things Lightweight
&lt;/h3&gt;

&lt;p&gt;For this particular use case, I wanted something simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A lightweight native module&lt;/li&gt;
&lt;li&gt;A clean JavaScript/TypeScript API&lt;/li&gt;
&lt;li&gt;Modern Android biometric APIs&lt;/li&gt;
&lt;li&gt;Promise-based authentication&lt;/li&gt;
&lt;li&gt;Minimal configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, instead of working around those limitations, I decided to build my own native module.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;code&gt;@vijeshkr/react-native-biometric-auth&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;@vijeshkr/react-native-biometric-auth&lt;/code&gt;&lt;/strong&gt; is an Android biometric authentication library for React Native, built with &lt;strong&gt;Kotlin&lt;/strong&gt; and &lt;strong&gt;AndroidX Biometric&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It provides biometric authentication with optional device credential fallback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kotlin Native Module&lt;/strong&gt; — Built entirely with Kotlin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AndroidX Biometric&lt;/strong&gt; — Uses Android's modern &lt;code&gt;BiometricPrompt&lt;/code&gt; APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device Credential Fallback&lt;/strong&gt; — Supports PIN, Pattern, or Password fallback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promise-Based API&lt;/strong&gt; — Works naturally with &lt;code&gt;async/await&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript Support&lt;/strong&gt; — Includes TypeScript definitions for a better developer experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simple React Native Integration&lt;/strong&gt; — Minimal setup and a straightforward API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Installation
&lt;/h3&gt;

&lt;p&gt;Install the package using npm:&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; @vijeshkr/react-native-biometric-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or using Yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @vijeshkr/react-native-biometric-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Check Availability and Authenticate
&lt;/h3&gt;

&lt;p&gt;Once installed, you can check whether authentication is available and then trigger the native Android authentication prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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&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;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SafeAreaView&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&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;BiometricAuth&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;@vijeshkr/react-native-biometric-auth&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;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;handleAuthentication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 1. Check if biometrics or device credentials are available&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAvailable&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;BiometricAuth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isBiometricAvailable&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;isAvailable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unavailable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Biometrics or device credentials are not set up on this device.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// 2. Trigger native BiometricPrompt&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;success&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;BiometricAuth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unlock Application&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Touch fingerprint sensor or enter device PIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cancelText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cancel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;allowDeviceCredential&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome back!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authentication Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authentication failed or was cancelled.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SafeAreaView&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&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;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Unlock App with Biometrics"&lt;/span&gt;
        &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAuthentication&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SafeAreaView&lt;/span&gt;&lt;span class="p"&gt;&amp;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;The API is intentionally simple: check availability, call &lt;code&gt;authenticate()&lt;/code&gt;, and handle the returned promise.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Work Under the Hood?
&lt;/h2&gt;

&lt;p&gt;The native Android implementation is written entirely in &lt;strong&gt;Kotlin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The module uses Android's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BiometricPrompt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BiometricManager&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;androidx.biometric&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;code&gt;allowDeviceCredential: true&lt;/code&gt; is enabled, the authentication flow allows the device credential to be used as a fallback.&lt;/p&gt;

&lt;p&gt;Conceptually, the authentication configuration uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;BIOMETRIC_STRONG&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="nc"&gt;DEVICE_CREDENTIAL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the user to authenticate using a supported strong biometric or their configured device credential, depending on the device and authentication setup.&lt;/p&gt;

&lt;p&gt;For example, if biometric authentication isn't available or the user chooses the available fallback, the device can use credentials such as a &lt;strong&gt;PIN, Pattern, or Password&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is one of the main reasons I wanted to build the module around the modern Android biometric APIs rather than implementing the authentication flow manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Kotlin?
&lt;/h2&gt;

&lt;p&gt;One of my goals with this project was to get more comfortable with the native side of React Native.&lt;/p&gt;

&lt;p&gt;React Native doesn't mean you only work with JavaScript or TypeScript.&lt;/p&gt;

&lt;p&gt;Sometimes you need to go one layer deeper and interact directly with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Native → Native Module → Android APIs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this project, Kotlin was a good fit because the Android side could remain small and focused while still taking advantage of modern Android APIs.&lt;/p&gt;

&lt;p&gt;Building this module also helped me better understand how React Native communicates with native Android code through a custom native module.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source
&lt;/h2&gt;

&lt;p&gt;The project is open source, and I'd love for other React Native developers to try it out and share their feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NPM Package:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@vijeshkr/react-native-biometric-auth" rel="noopener noreferrer"&gt;@vijeshkr/react-native-biometric-auth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/vijeshkr/react-native-biometric-auth" rel="noopener noreferrer"&gt;vijeshkr/react-native-biometric-auth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find the project useful, consider giving it a star on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;This is currently focused on &lt;strong&gt;Android biometric authentication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are several things I would like to explore as the project evolves, including improvements to the authentication flow, documentation, testing, and potentially broader platform support.&lt;/p&gt;

&lt;p&gt;I also want to continue improving my understanding of React Native's native module architecture through projects like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Discuss
&lt;/h2&gt;

&lt;p&gt;I'd love to hear from other React Native developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you faced any challenges while implementing biometric or native authentication in React Native?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What feature would you like to see added to this library next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Feel free to share your experience or suggestions in the comments.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>android</category>
      <category>kotlin</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
