<?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: john mbugua</title>
    <description>The latest articles on DEV Community by john mbugua (@mbugua70).</description>
    <link>https://dev.to/mbugua70</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg</url>
      <title>DEV Community: john mbugua</title>
      <link>https://dev.to/mbugua70</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbugua70"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 07 Feb 2026 13:44:58 +0000</pubDate>
      <link>https://dev.to/mbugua70/-132a</link>
      <guid>https://dev.to/mbugua70/-132a</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/mbugua70" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" alt="mbugua70"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/mbugua70/local-vs-cloud-builds-in-expo-what-expo-prebuild-and-eas-build-really-do-3mnc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Local vs Cloud Builds in Expo: What expo prebuild and eas build Really Do&lt;/h2&gt;
      &lt;h3&gt;john mbugua ・ Feb 7&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#reactnative&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#mobile&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>reactnative</category>
      <category>programming</category>
      <category>react</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Local vs Cloud Builds in Expo: What expo prebuild and eas build Really Do</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 07 Feb 2026 13:44:39 +0000</pubDate>
      <link>https://dev.to/mbugua70/local-vs-cloud-builds-in-expo-what-expo-prebuild-and-eas-build-really-do-3mnc</link>
      <guid>https://dev.to/mbugua70/local-vs-cloud-builds-in-expo-what-expo-prebuild-and-eas-build-really-do-3mnc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;There’s a lot of confusion around terms like &lt;strong&gt;Prebuild&lt;/strong&gt;, &lt;strong&gt;Dev&lt;/strong&gt; &lt;strong&gt;Client&lt;/strong&gt;, &lt;strong&gt;EAS Build&lt;/strong&gt;, and &lt;strong&gt;Continuous Native Generation (CNG)&lt;/strong&gt;. I remember the confusion I used to have myself especially when trying to understand the difference between EAS cloud builds and local builds.&lt;/p&gt;

&lt;p&gt;For a long time, I assumed that a local build was the same thing as the &lt;strong&gt;CNG&lt;/strong&gt; process. I kept asking myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the logic behind each build?&lt;/li&gt;
&lt;li&gt;What’s the real difference between &lt;strong&gt;cloud builds&lt;/strong&gt;  and &lt;strong&gt;local builds&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What do you actually gain from using &lt;strong&gt;EAS&lt;/strong&gt; Build versus building locally?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At some point, the questions got even more confusing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was EAS Build ignoring my native code?&lt;/li&gt;
&lt;li&gt;And where did &lt;strong&gt;CNG&lt;/strong&gt; fit into all of this?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The confusion didn’t come from the tools themselves, it came from not understanding how they connect.&lt;/p&gt;

&lt;p&gt;Once I finally understood what &lt;strong&gt;CNG&lt;/strong&gt; really is, how Prebuild fits into it, and how both local builds and cloud builds rely on the same native generation system, everything clicked.&lt;/p&gt;

&lt;p&gt;So before comparing cloud builds and local builds, let’s first talk about CNG.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Continuous Native Generation (CNG)?
&lt;/h2&gt;

&lt;p&gt;When I was learning React Native, I remember a time when CNG was not really a thing yet. Building an app that included native modules often meant ejecting from your project whether you were using &lt;strong&gt;Expo&lt;/strong&gt; or &lt;strong&gt;React Native CLI&lt;/strong&gt;. Once you ejected, you were suddenly responsible for configuring native code &lt;strong&gt;manually&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Does this look familiar? 😅 &lt;em&gt;The old managed vs bare workflow era&lt;/em&gt;…&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expo eject --eject-method=bare

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

&lt;/div&gt;



&lt;p&gt;Or even better, the interactive prompt where you had to choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bare workflow (eject)&lt;/li&gt;
&lt;li&gt;Managed workflow (stay)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Working with native modules meant editing things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AndroidManifest.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Gradle files&lt;/li&gt;
&lt;li&gt;iOS &lt;code&gt;Info.plist&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;platform-specific permissions and setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of that, some libraries only supported older OS versions, and getting them to work correctly with your app could be frustrating. Upgrading React Native or adding new native functionality often felt risky, because one wrong change could break the entire build.&lt;/p&gt;

&lt;p&gt;Then &lt;strong&gt;CNG&lt;/strong&gt; came in and changed the workflow completely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous Native Generation (CNG)&lt;/strong&gt; is Expo’s approach to managing native code in a React Native app. Before &lt;strong&gt;CNG&lt;/strong&gt;, native projects were usually created once and then manually maintained for the entire lifetime of the app. Over time, this made native code fragile, hard to upgrade, and difficult to reason about.&lt;/p&gt;

&lt;p&gt;Instead of treating native projects as something you create once and protect forever, &lt;strong&gt;CNG&lt;/strong&gt; treats them as short-lived, generated artifacts. Native projects are created only when needed such as during development, debugging, or building and they are generated from a standard template plus a set of configuration rules.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;CNG&lt;/strong&gt;, developers don’t maintain the native projects themselves. They maintain the instructions for how those native projects should be created.&lt;/p&gt;

&lt;p&gt;Those instructions live in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app.json&lt;/code&gt; or &lt;code&gt;app.config.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;config plugins provided by libraries or written by the developer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Expo needs native code, it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starts from a clean native template&lt;/li&gt;
&lt;li&gt;Applies the configuration and config plugins&lt;/li&gt;
&lt;li&gt;Generates the Android and iOS projects&lt;/li&gt;
&lt;li&gt;Builds the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, we now know what &lt;strong&gt;CNG&lt;/strong&gt; is and why it exists. It’s the system responsible for generating native projects in a predictable and repeatable way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CNG&lt;/strong&gt; itself doesn’t build your app  it prepares the native code that builds depend on. Tools like &lt;strong&gt;Prebuild&lt;/strong&gt;, local &lt;strong&gt;dev&lt;/strong&gt; builds, and EAS cloud builds all rely on this same native generation process.&lt;/p&gt;

&lt;p&gt;With that foundation in place, we can now clearly compare local builds and EAS cloud builds, understand what each one actually does, and see how &lt;strong&gt;CNG&lt;/strong&gt; fits into both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local Builds vs EAS Builds
&lt;/h2&gt;

&lt;p&gt;Before comparing &lt;em&gt;local builds&lt;/em&gt; and &lt;em&gt;EAS builds&lt;/em&gt;, it’s important to clarify what we actually mean by “local build”  because this is where a lot of confusion starts 😅.&lt;/p&gt;

&lt;p&gt;When I say local build, I’m referring to building your native app on your own machine, where the Android and iOS projects (&lt;strong&gt;/android&lt;/strong&gt; and &lt;strong&gt;/ios&lt;/strong&gt;) are generated locally and compiled using your local environment.&lt;/p&gt;

&lt;p&gt;That usually looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native projects are generated locally&lt;/li&gt;
&lt;li&gt;You can open Android Studio or Xcode&lt;/li&gt;
&lt;li&gt;You can run and debug the app directly on your machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, to make things a little more confusing (because of course 😄), we also have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eas build --local

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

&lt;/div&gt;



&lt;p&gt;Which allows you to run the &lt;strong&gt;EAS&lt;/strong&gt; Build pipeline locally, instead of on &lt;strong&gt;Expo’s servers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So now we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local builds using &lt;code&gt;npx expo prebuild&lt;/code&gt; + &lt;code&gt;npx expo run:*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;local builds using &lt;code&gt;eas build --local&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cloud builds using &lt;code&gt;eas build&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first glance, this can make it feel &lt;em&gt;like there are many different build systems&lt;/em&gt;. But here’s the key point:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All of these builds rely on the same underlying system: Continuous Native Generation (CNG).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you build locally or in the cloud, native projects are always generated using &lt;strong&gt;CNG&lt;/strong&gt;. The difference between these workflows is not how native code is generated  it’s where the build runs and what the workflow is optimized for.&lt;/p&gt;

&lt;p&gt;With that in mind, we can now clearly break down the differences between local builds and EAS cloud builds, and understand when each one makes sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local Builds (Dev Client Builds)
&lt;/h2&gt;

&lt;p&gt;When we talk about &lt;strong&gt;local builds&lt;/strong&gt; in Expo, we’re usually referring to building and running the app on your own machine, with native projects generated locally. This is the workflow most developers use during active development and debugging.&lt;/p&gt;

&lt;p&gt;Local builds are powered by &lt;strong&gt;Prebuild&lt;/strong&gt;, which is Expo’s implementation of &lt;strong&gt;Continuous Native Generation (CNG)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;when you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx expo prebuild

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

&lt;/div&gt;



&lt;p&gt;Expo generates the native Android and iOS projects (&lt;strong&gt;/android&lt;/strong&gt; and &lt;strong&gt;/ios&lt;/strong&gt;) from your app configuration and installed libraries. These native projects are created so your React Native code can be compiled and run as a real native app.&lt;/p&gt;

&lt;p&gt;Once the native projects exist, you can run the app locally using.&lt;/p&gt;

&lt;p&gt;Android:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx expo run:android

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

&lt;/div&gt;



&lt;p&gt;IOS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx expo run:ios

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

&lt;/div&gt;



&lt;p&gt;This compiles and launches the app using your local Android or iOS development environment, allowing you to debug the app, inspect logs, and even open the project in Android Studio or Xcode.&lt;/p&gt;

&lt;h3&gt;
  
  
  A quick but important note about modifying native files
&lt;/h3&gt;

&lt;p&gt;Because the native projects are generated by Prebuild, modifying them manually comes with a tradeoff.&lt;/p&gt;

&lt;p&gt;If you later run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx expo prebuild --clean

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

&lt;/div&gt;



&lt;p&gt;Expo will delete and regenerate the native projects. Any manual changes made directly inside &lt;em&gt;/android&lt;/em&gt; or &lt;em&gt;/ios&lt;/em&gt; can be lost.&lt;/p&gt;

&lt;p&gt;That’s why Expo encourages developers to use &lt;strong&gt;config plugins&lt;/strong&gt; instead of editing native files directly. Config plugins are functions that apply native changes automatically during &lt;strong&gt;Prebuild&lt;/strong&gt;, making those changes repeatable and safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  EAS Build (Cloud Builds)
&lt;/h2&gt;

&lt;p&gt;While local builds are great for development and debugging, they’re not always ideal for packaging, distributing, or shipping apps. This is where &lt;strong&gt;EAS Build&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;EAS Build is Expo’s cloud-based build service. Instead of compiling your Android or iOS app on your machine, the entire build process runs on &lt;strong&gt;Expo’s servers&lt;/strong&gt;, producing installable artifacts like &lt;em&gt;APKs&lt;/em&gt;, &lt;em&gt;AABs&lt;/em&gt;, or IPAs.&lt;/p&gt;

&lt;p&gt;At its simplest, running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eas build --platform all

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

&lt;/div&gt;



&lt;p&gt;Uploads your project to &lt;strong&gt;EAS Build&lt;/strong&gt;, where it is compiled in a clean, consistent environment for both Android and iOS. &lt;/p&gt;

&lt;h3&gt;
  
  
  How EAS Build works with CNG
&lt;/h3&gt;

&lt;p&gt;This is where a lot of confusion usually comes from.&lt;/p&gt;

&lt;p&gt;EAS Build does not replace &lt;em&gt;Continuous Native Generation (CNG)&lt;/em&gt;. It uses it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your project does not have &lt;em&gt;/android&lt;/em&gt; and &lt;em&gt;/ios&lt;/em&gt; folders, EAS Build will run Prebuild (CNG) in the cloud to generate them.&lt;/li&gt;
&lt;li&gt;If your project already has &lt;em&gt;/android&lt;/em&gt; and &lt;em&gt;/ios&lt;/em&gt;, EAS Build will use those native projects as they are and will not regenerate them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either way, native code is still prepared using the same &lt;strong&gt;CNG system&lt;/strong&gt;. The difference is simply where the process runs and who compiles the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  What EAS Build is really good at
&lt;/h3&gt;

&lt;p&gt;EAS Build is optimized for distribution and automation, not daily iteration. It shines when you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build production-ready binaries for app stores&lt;/li&gt;
&lt;li&gt;share builds with testers using internal distribution links&lt;/li&gt;
&lt;li&gt;avoid local Android or iOS environment setup&lt;/li&gt;
&lt;li&gt;ensure consistent builds across a team&lt;/li&gt;
&lt;li&gt;automate builds using CI or EAS Workflows&lt;/li&gt;
&lt;li&gt;manage signing credentials without manual setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because builds run in the cloud, every build starts from a clean environment, reducing “works on my machine” problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The key takeaway
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;EAS Build focuses on packaging, distribution, and automation.&lt;br&gt;
Local builds focus on fast iteration and debugging.&lt;br&gt;
Both rely on the same CNG system underneath.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you understand that, the relationship between local builds, cloud builds, and native code becomes much easier to reason about.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>programming</category>
      <category>react</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Happy coding</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 24 Jan 2026 19:31:56 +0000</pubDate>
      <link>https://dev.to/mbugua70/happy-coding-4l8</link>
      <guid>https://dev.to/mbugua70/happy-coding-4l8</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o" class="crayons-story__hidden-navigation-link"&gt;React Render vs Commit: What Actually Happens (DOM vs React Native)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mbugua70" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" alt="mbugua70 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mbugua70" class="crayons-story__secondary fw-medium m:hidden"&gt;
              john mbugua
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                john mbugua
                
              
              &lt;div id="story-author-preview-content-3196186" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mbugua70" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;john mbugua&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o" id="article-link-3196186"&gt;
          React Render vs Commit: What Actually Happens (DOM vs React Native)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/react"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;react&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/reactnative"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;reactnative&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;4&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>react</category>
      <category>reactnative</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Render vs Commit: What Actually Happens (DOM vs React Native)</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 24 Jan 2026 19:23:02 +0000</pubDate>
      <link>https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o</link>
      <guid>https://dev.to/mbugua70/react-render-vs-commit-what-actually-happens-dom-vs-react-native-2f7o</guid>
      <description>&lt;p&gt;I know we’ve all heard these phrases: “React rendering” and “React commit” and if you’ve ever profiled a React Native app, you’ve probably seen logs or profiler entries like “committed.” It’s an interesting topic: &lt;em&gt;how React works when it’s rendering and committing changes, whether that’s to the DOM (on the web) or to native UI views (in React Native)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So let’s start with something small but important: &lt;strong&gt;React’s render phase and commit phase&lt;/strong&gt;. We’ll look at how updates get scheduled across the component tree, what actually causes React to render, what reconciliation means, why some renders don’t result in visible UI changes, and how optimization starts to matter once rendering becomes a performance bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  What causes a component to render?
&lt;/h2&gt;

&lt;p&gt;A component renders when React thinks something in that part of the tree might have changed. The most common triggers are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State updates (useState, useReducer, class setState)&lt;/li&gt;
&lt;li&gt;Props changes from a parent&lt;/li&gt;
&lt;li&gt;Context updates (any consumers of that context may re-render)&lt;/li&gt;
&lt;li&gt;Store updates (Redux/Zustand/MobX subscriptions)&lt;/li&gt;
&lt;li&gt;A parent re-render, which can cause React to re-run children while computing the next UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once any of these happen, React schedules work and begins the update process. And this is where the two phases come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two-phase model: render phase &amp;amp; commit phase
&lt;/h2&gt;

&lt;p&gt;The easiest way to think about React updates is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Render phase computes the next UI. Commit phase applies it to the real platform 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.amazonaws.com%2Fuploads%2Farticles%2Fufnncb7dv6bjvzn5dgdj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufnncb7dv6bjvzn5dgdj.png" alt=" " width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Render phase
&lt;/h2&gt;

&lt;p&gt;On the left side of the image is the Render Phase. This is where React does &lt;em&gt;planning&lt;/em&gt;, not &lt;em&gt;painting&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1) JSX becomes React elements
&lt;/h3&gt;

&lt;p&gt;In my diagram, JSX flows into a React element via &lt;code&gt;createElement()&lt;/code&gt;. That’s exactly the idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSX is just syntax.&lt;/li&gt;
&lt;li&gt;It becomes React elements (plain objects describing type + props + children).&lt;/li&gt;
&lt;li&gt;This step is the same in React DOM and React Native.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;React elements are not DOM nodes and not native views, &lt;em&gt;they’re the description of what you want&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Current tree vs Work-in-progress tree
&lt;/h3&gt;

&lt;p&gt;When an update happens (state/props change), React doesn’t immediately touch the screen. Instead, it builds a new version of the UI internally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Current tree&lt;/strong&gt;: the last committed version (what the user is currently seeing)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work-in-progress tree&lt;/strong&gt;: the next version React is building based on the new state/props&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3) Reconciliation
&lt;/h3&gt;

&lt;p&gt;That “Compare React Element/Reconciliation” arrow in my image represents the core job of the render phase. &lt;br&gt;
React compares what the UI looked like before (current) with what it should look like now (work-in-progress) and figures out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what stays the same&lt;/li&gt;
&lt;li&gt;what needs to update&lt;/li&gt;
&lt;li&gt;what should be added&lt;/li&gt;
&lt;li&gt;what should be removed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4) Output of render phase
&lt;/h3&gt;

&lt;p&gt;At the end of the render phase, React produces what I have called in the  diagram &lt;strong&gt;changes&lt;/strong&gt;, basically a list of “things the renderer must do.”&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The screen hasn’t changed yet. React has only computed what should change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Commit phase
&lt;/h2&gt;

&lt;p&gt;Now we move to the right side of the image  &lt;strong&gt;the Commit Phase&lt;/strong&gt;. This is where React stops planning and starts applying. React core hands the “changes” to a renderer. &lt;/p&gt;

&lt;h3&gt;
  
  
  React Native commit
&lt;/h3&gt;

&lt;p&gt;React Native applies those changes by &lt;em&gt;creating/updating/removing&lt;/em&gt; native view instances, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;li&gt;Text&lt;/li&gt;
&lt;li&gt;Image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So commit in React Native means: &lt;strong&gt;update the native UI tree&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  React DOM commit
&lt;/h3&gt;

&lt;p&gt;React DOM applies those changes by &lt;em&gt;creating/updating/removing&lt;/em&gt; DOM nodes,elements in the browser DOM tree.&lt;br&gt;
So commit on the web means: &lt;strong&gt;update the DOM&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unnecessary renders
&lt;/h2&gt;

&lt;p&gt;Now that we’ve seen the big picture &lt;em&gt;(render phase - commit phase)&lt;/em&gt;, this second diagram shows a very common performance situation: a component re-renders, but nothing visually changes. That’s what people usually mean when they say unnecessary (or wasted) renders.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  The setup
&lt;/h3&gt;

&lt;p&gt;In the diagram, the Parent component is flagged because its state or props changed. That could be a button press, a text input update, a timer tick, a fetch response, anything that triggers a state/props update.&lt;/p&gt;

&lt;p&gt;Once the parent is &lt;strong&gt;flagged&lt;/strong&gt;, React schedules work and starts the render phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens in the render phase (and why children get involved)
&lt;/h3&gt;

&lt;p&gt;During the render phase, React re-runs the parent to compute the next UI. But it doesn’t stop there.&lt;/p&gt;

&lt;p&gt;Because the parent’s output may include &lt;strong&gt;children&lt;/strong&gt;, React will typically continue into the &lt;strong&gt;subtree&lt;/strong&gt; and re-run child components too, so it can build the next &lt;strong&gt;work-in-progress&lt;/strong&gt; tree.&lt;/p&gt;

&lt;p&gt;That’s the key idea of the diagram is showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parent changes → React re-runs Parent&lt;/li&gt;
&lt;li&gt;React attempts to render its children as part of building the next tree&lt;/li&gt;
&lt;li&gt;React produces the next output (React elements)&lt;/li&gt;
&lt;li&gt;React compares *&lt;strong&gt;*Current tree vs **Work-in-progress&lt;/strong&gt; tree (reconciliation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The “unnecessary render” moment
&lt;/h3&gt;

&lt;p&gt;Here’s the important part: &lt;em&gt;the child re-rendered, but its output didn’t change&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So what does React do?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The child component function still ran (render work happened)&lt;/li&gt;
&lt;li&gt;Reconciliation still compared old vs new output&lt;/li&gt;
&lt;li&gt;But since the child output was the same, React produces no host updates for that child&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means when React gets to the &lt;strong&gt;commit phase&lt;/strong&gt;, there’s nothing to apply for that &lt;strong&gt;child subtree&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React Native&lt;/strong&gt;: no new/updated/removed native view instances for that child&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React DOM&lt;/strong&gt;: no meaningful DOM mutations for that child&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the render happened, but the commit work for that child was basically a &lt;strong&gt;no-op&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is why it’s called wasted work:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You paid the cost of re-running the component and reconciling it, but you didn’t get any UI change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why unnecessary renders matter in profiling
&lt;/h3&gt;

&lt;p&gt;When profiling, this is exactly why you might see: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;many component renders,&lt;/li&gt;
&lt;li&gt;but very little commit activity,&lt;/li&gt;
&lt;li&gt;and still feel the app getting slower (especially on lower-end devices).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the cost you’re paying is mostly on the &lt;strong&gt;JavaScript side&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;executing component functions&lt;/li&gt;
&lt;li&gt;running hooks&lt;/li&gt;
&lt;li&gt;reconciling children&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if commit is small, lots of wasted render work can still block the JS thread and create jank.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Unnecessary renders happen when a parent update causes a child to re-render during the render phase, but the child’s output stays the same, so there are no actual UI changes to commit.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 10 Jan 2026 20:19:36 +0000</pubDate>
      <link>https://dev.to/mbugua70/-56ef</link>
      <guid>https://dev.to/mbugua70/-56ef</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02" class="crayons-story__hidden-navigation-link"&gt;React Native Optimization: Stop Recreating Functions in Large Lists (FlatList, Flashlist, LegendList...)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mbugua70" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" alt="mbugua70 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mbugua70" class="crayons-story__secondary fw-medium m:hidden"&gt;
              john mbugua
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                john mbugua
                
              
              &lt;div id="story-author-preview-content-3163220" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mbugua70" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;john mbugua&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 10&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02" id="article-link-3163220"&gt;
          React Native Optimization: Stop Recreating Functions in Large Lists (FlatList, Flashlist, LegendList...)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/reactnative"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;reactnative&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/react"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;react&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/softwaredevelopment"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwaredevelopment&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>reactnative</category>
      <category>react</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Native Optimization: Stop Recreating Functions in Large Lists (FlatList, Flashlist, LegendList...)</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 10 Jan 2026 19:51:39 +0000</pubDate>
      <link>https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02</link>
      <guid>https://dev.to/mbugua70/react-native-optimization-stop-recreating-functions-in-large-lists-flatlist-flashlist-d02</guid>
      <description>&lt;p&gt;A practical guide to optimizing list performance in React Native by memoizing renderItem and callbacks to prevent unnecessary re-renders.&lt;/p&gt;

&lt;p&gt;When a React Native screen starts feeling  (Heavy, janky scroll, dropped frames), it’s often not one big issue, it’s lots of small ones stacking up.One of the most common (and easiest to fix) is &lt;strong&gt;inline functions in large lists&lt;/strong&gt;. This applies to &lt;code&gt;FlatList&lt;/code&gt;, &lt;code&gt;SectionList&lt;/code&gt;, &lt;code&gt;LegendList&lt;/code&gt;, Shopify &lt;code&gt;FlashList&lt;/code&gt;, and pretty much any component that renders many rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why inline functions hurt list performance
&lt;/h2&gt;

&lt;p&gt;In JavaScript, functions are objects. That means every time your component re-renders, any inline function you write is created again with a &lt;strong&gt;new reference&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;LegendList
  data={data}
  renderItem={({ item }) =&amp;gt; (
    &amp;lt;Row
      item={item}
      onPress={() =&amp;gt; handlePress(item.id)} // new function every render
    /&amp;gt;
  )}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if &lt;code&gt;item&lt;/code&gt; didn’t change, &lt;code&gt;onPress={() =&amp;gt; ...}&lt;/code&gt; is a brand new function each render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does that matter?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If Row is memoized, it can still re-render because a prop changed (new function reference).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In big lists, that means more work for the JS thread, more layout work, and a higher chance of scroll stutters.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not “never use inline functions.” The goal is: &lt;strong&gt;don’t create new function references for every row, every render,&lt;/strong&gt; especially when the list is large.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memoize renderItem with useCallback
&lt;/h2&gt;

&lt;p&gt;First, make renderItem stable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const renderItem = useCallback(({ item }) =&amp;gt; {
  return &amp;lt;Row item={item} /&amp;gt;;
}, []);

return (
  &amp;lt;FlatList
    data={data}
    renderItem={renderItem}
    keyExtractor={(item) =&amp;gt; item.id}
  /&amp;gt;
);

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

&lt;/div&gt;



&lt;p&gt;Now renderItem won’t be recreated on every screen re-render.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cool — but what about row actions?
&lt;/h3&gt;

&lt;p&gt;At this point &lt;code&gt;renderItem&lt;/code&gt; is stable, which is a big win.&lt;br&gt;&lt;br&gt;
But sometimes items usually have actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tap to open details&lt;/li&gt;
&lt;li&gt;long-press to show a menu&lt;/li&gt;
&lt;li&gt;swipe / delete&lt;/li&gt;
&lt;li&gt;“call customer”, “copy code”, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this is where many apps accidentally bring the problem back.&lt;/p&gt;
&lt;h4&gt;
  
  
  The common trap: inline callbacks per row
&lt;/h4&gt;

&lt;p&gt;You will often have/see something 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;const renderItem = useCallback(({ item }) =&amp;gt; (
  &amp;lt;Row
    item={item}
    onPress={() =&amp;gt; handleOpen(item.id)}
    onLongPress={() =&amp;gt; handleMenu(item)}
  /&amp;gt;
), [handleOpen, handleMenu]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though &lt;code&gt;renderItem&lt;/code&gt; is &lt;code&gt;memoized&lt;/code&gt;, those &lt;code&gt;() =&amp;gt; ...&lt;/code&gt; functions are still created when renderItem runs. That means every row receives new callback references, which can cause Row to re-render even when the UI didn’t actually change.&lt;/p&gt;

&lt;p&gt;So what's the next goal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep handlers stable, and avoid generating new functions for each item inside renderItem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The better pattern: pass stable handlers, let the row provide the id&lt;/strong&gt; Instead of binding item inside renderItem, pass a stable function down and let the row call it with its own identifier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const onPressItem = useCallback((id: string) =&amp;gt; {
  handleOpen(id);
}, [handleOpen]);

const onLongPressItem = useCallback((id: string) =&amp;gt; {
  handleMenu(id);
}, [handleMenu]);

const renderItem = useCallback(({ item }) =&amp;gt; {
  return (
    &amp;lt;Row
      item={item}
      onPressItem={onPressItem}
      onLongPressItem={onLongPressItem}
    /&amp;gt;
  );
}, [onPressItem, onLongPressItem]);

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

&lt;/div&gt;



&lt;p&gt;Now, as long as&lt;code&gt;handleOpen&lt;/code&gt; and &lt;code&gt;handleMenu&lt;/code&gt; don’t change, the function references stay stable.&lt;/p&gt;

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

&lt;p&gt;When you are  working with large lists in React Native, the small things matter. Memoizing &lt;code&gt;renderItem&lt;/code&gt; and avoiding inline callbacks helps keep references stable, which means fewer unnecessary row re-renders and smoother scrolling.&lt;/p&gt;

&lt;p&gt;You don’t have to over optimize every screen, but for list heavy UIs, these changes are some of the highest  wins you can make.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acknowledgement:&lt;/strong&gt; Big thanks to the team at &lt;strong&gt;Callstack&lt;/strong&gt; for their webinar on React Native optimization a lot of the ideas here clicked for me through that talk.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sun, 05 Oct 2025 09:50:44 +0000</pubDate>
      <link>https://dev.to/mbugua70/-5apo</link>
      <guid>https://dev.to/mbugua70/-5apo</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3" class="crayons-story__hidden-navigation-link"&gt;Two Apps, One Device: Dynamic app.config.(js|ts) in Expo&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mbugua70" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" alt="mbugua70 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mbugua70" class="crayons-story__secondary fw-medium m:hidden"&gt;
              john mbugua
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                john mbugua
                
              
              &lt;div id="story-author-preview-content-2893953" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mbugua70" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F813366%2F5d34c017-66c9-4c37-ad00-4fce364492d2.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;john mbugua&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 5 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3" id="article-link-2893953"&gt;
          Two Apps, One Device: Dynamic app.config.(js|ts) in Expo
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/reactnative"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;reactnative&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mobile"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mobile&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/buildinpublic"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;buildinpublic&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>programming</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Two Apps, One Device: Dynamic app.config.(js|ts) in Expo</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sun, 05 Oct 2025 09:50:10 +0000</pubDate>
      <link>https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3</link>
      <guid>https://dev.to/mbugua70/two-apps-one-device-dynamic-appconfigjsts-in-expo-1ml3</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What is &lt;code&gt;app.config.(js|ts), app.json&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;A quick story&lt;/li&gt;
&lt;li&gt;Why this matters&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In my React Native + Expo workflow I run three environments: development, preview, and production. I use development for day to day coding and to take full advantage of Expo’s dev tools and fast iteration. Preview mimics production so I can see exactly how the app will behave before a release, no debug extras, realistic settings. Production is the real, ready build for users. With a dynamic &lt;strong&gt;app.config.(js|ts)&lt;/strong&gt;, I can keep all three installed side by side on one device.✅&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;code&gt;app.config.(js|ts), app.json&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;It's a file used for configuring Expo Prebuild, platform settings (names, bundle IDs, icons, deep-link schemes, OTA update channels, plugins, etc.)&lt;br&gt;
It must be located at the root of your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it can contain (most common properties)&lt;/strong&gt;&lt;br&gt;
The app config configures many things such as app name, icon, splash screen, deep linking scheme, API keys to use for some services and so on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity&lt;/strong&gt;: name, slug, owner, version&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform IDs&lt;/strong&gt;: ios.bundleIdentifier, android.package&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep links&lt;/strong&gt;: scheme, intentFilters (Android), associated domains (iOS)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assets &amp;amp; UI&lt;/strong&gt;: icon, splash, adaptiveIcon, userInterfaceStyle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updates/OTA&lt;/strong&gt;: updates.channel or runtimeVersion policy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions &amp;amp; platform options&lt;/strong&gt;: e.g., Bluetooth, camera, android.permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build tooling&lt;/strong&gt;: plugins, experiments, newArchEnabled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime flags&lt;/strong&gt;: extra (and EXPO_PUBLIC_* envs) for reading inside your app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Static vs dynamic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Static(json)&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "expo": { "name": "MyApp", "ios": { "bundleIdentifier": "com.company.myapp" } }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Dynamic(json)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dynamic configuration in Expo lets you generate your app settings at build time using real JavaScript/TypeScript. That means you can branch on environment variables, &lt;em&gt;tweak names/IDs/icons/schemes&lt;/em&gt; per build, and expose safe runtime flags all from one file. Below are the key points; you can dive deeper in the official &lt;a href="https://docs.expo.dev/workflow/configuration/" rel="noopener noreferrer"&gt;Expo Docs&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can write your config in JavaScript (app.config.js) or TypeScript (app.config.ts) for more flexibility.&lt;/li&gt;
&lt;li&gt;In these files you can use comments, variables, and single quotes—it’s just regular JS/TS.&lt;/li&gt;
&lt;li&gt;ES module import isn’t supported in plain JS. Use require() instead.
(Exception: TypeScript with tsx can use import.)&lt;/li&gt;
&lt;li&gt;In dynamic configs, you can use modern JavaScript features like optional chaining (?.) and nullish coalescing (??). They work in app.config.ts via TS, and in app.config.js as long as your Node version supports ES2020 (Node 14+ recommended).&lt;/li&gt;
&lt;li&gt;The config is re-evaluated on Metro reload, so changes show up when the bundler refreshes.&lt;/li&gt;
&lt;li&gt;You can read env vars (e.g., process.env.APP_VARIANT) to pass environment info into your app (via extra or EXPO_PUBLIC_*).&lt;/li&gt;
&lt;li&gt;The config must be synchronous—no Promises/async code inside.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.config.ts
const ENV = process.env.APP_VARIANT ?? 'production'; // env info

export default ({ config }) =&amp;gt; {
  const isDev = ENV === 'development'; // variables + single quotes

  const name = isDev ? 'MyApp (Dev)' : 'MyApp';

  return {
    ...config,
    name,
    ios: { bundleIdentifier: isDev ? 'com.me.myapp.dev' : 'com.me.myapp' },
    android: { package: isDev ? 'com.me.myapp.dev' : 'com.me.myapp' },
    extra: { APP_VARIANT: ENV }, // expose to app at runtime
  };
};

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  A quick story
&lt;/h2&gt;

&lt;p&gt;For a long time I shipped with a static app.json. It worked until testing time. I needed the production build to feel what users feel, and the development build for my daily work. But with one static config &lt;em&gt;(one bundle ID, one scheme)&lt;/em&gt;, my phone couldn’t keep both installed. Every test cycle became: &lt;em&gt;uninstall dev → install prod/preview → test → uninstall prod/preview → reinstall dev → keep coding&lt;/em&gt;. It was slow, tiresome, and I constantly second guessed whether I was testing the right thing. Thanks to dynamic configuration, I can now keep both environments on my phone and test each app side-by-side—no more uninstall/reinstall dance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;You want dev, preview, and prod to coexist on the same phone. That only works if each build has a unique identity. Dynamic &lt;code&gt;app.config.js&lt;/code&gt; lets you generate those identities from one codebase .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works&lt;/strong&gt;&lt;br&gt;
Expo reads your &lt;code&gt;app.config.js&lt;/code&gt; at build time. Because it’s JavaScript, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look at an env variable (here: &lt;code&gt;process.env.APP_VARIANT&lt;/code&gt;)🕰️.&lt;/li&gt;
&lt;li&gt;Branch the config to change names✳️&lt;/li&gt;
&lt;li&gt;Return a plain object, Expo uses it to produce native projects with those values❇️.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Core idea: different IDs → different apps. iOS uses &lt;code&gt;bundleIdentifier&lt;/code&gt;; Android uses &lt;code&gt;package&lt;/code&gt;. If these differ, the OS treats them as different apps that can be installed side-by-side. Below is just a sample of my app.config.js&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default ({ config }) =&amp;gt; ({
  ...config,
  name: getAppName(),
  slug: "tkt-app",
  owner: "iguru-ltd",
  version: "2.2.0",
  orientation: "portrait",
  icon: "./assets/images/icon.png",
  scheme: "tktapp",
  userInterfaceStyle: "automatic",
  newArchEnabled: true,
  ios: {
     // other configs for ios
    bundleIdentifier: getUniqueIdentifier(),
  },
  android: {
    // other config for android
    package: getUniqueIdentifier(),
    runtimeVersion: "1.0.0",
  },
  web: {
    bundler: "metro",
    output: "static",
    favicon: "./assets/images/favicon.png",
  },
  plugins: [
   // all the plugins configurations will go here/ some will appear here during installion
  ],
  experiments: {
    typedRoutes: true,
  },
  updates: {
     //configs for OTA update
    },
  extra: {
   // may include your project id for eas build

  },
});

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Export a function that returns your config&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This makes the file dynamic, you can compute values first, then return them, Allowing you to add your own custom config.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default ({ config }) =&amp;gt; ({
  ...config,
  // ...all your fields
});

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Read the environment &amp;amp; set helpers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can have different configuration in development, staging, and production environments. These flags drive everything that changes per build. To accomplish this, you can use app.config.js along with environment variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const IS_DEV = process.env.APP_VARIANT === "development";
const IS_PREVIEW = process.env.APP_VARIANT === "preview";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Change the app name per environment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visible on-device so you don’t tap the wrong one. I love to have a helper function that return the App name based on the environment i am working on.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getAppName = () =&amp;gt; {
  if (IS_DEV) return "TKT APP (Dev)";
  if (IS_PREVIEW) return "TKT APP (Preview)";
  return "TKT APP"; // production
};

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Change the native identifiers (the key to parallel installs)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getUniqueIdentifier = () =&amp;gt; {
  if (IS_DEV) return "com.mbuguacode.tktapp.dev";
  if (IS_PREVIEW) return "com.mbuguacode.tktapp.preview";
  return "com.mbuguacode.tktapp"; // production
};

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;All your Bluetooth permissions, splash config, and plugins remain the same, dynamic config only overrides what must differ.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;A quick: &lt;em&gt;how Expo turns this into separate apps&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run a build with &lt;code&gt;APP_VARIANT=development&lt;/code&gt; (or &lt;code&gt;preview/production&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.config.js&lt;/code&gt; returns an object with unique &lt;code&gt;name&lt;/code&gt; + &lt;code&gt;unique bundleIdentifier/package&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EAS/CLI&lt;/code&gt; generates native projects with those identifiers.&lt;/li&gt;
&lt;li&gt;The OS treats each identifier as a different app → they install side-by-side.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;My take is: this isn’t about fancy tooling, it’s about mindset. Treating config as code has been the quiet upgrade that changed my day-to-day coding. I hope this article sparks something for you too maybe it’s setting up that second environment, maybe it’s finally badging your icons, or just tightening your release path.Kudos!🙌&lt;/p&gt;

&lt;p&gt;Learn more on the official &lt;a href="https://docs.expo.dev/workflow/configuration/" rel="noopener noreferrer"&gt;Expo Docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>programming</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Implementing JWT Authentication in Node.js</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Fri, 05 Jul 2024 04:52:53 +0000</pubDate>
      <link>https://dev.to/mbugua70/implementing-jwt-authentication-in-nodejs-3m8g</link>
      <guid>https://dev.to/mbugua70/implementing-jwt-authentication-in-nodejs-3m8g</guid>
      <description>&lt;h2&gt;
  
  
  Page Content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to JSON Web Token&lt;/li&gt;
&lt;li&gt;What is JSON Web Token&lt;/li&gt;
&lt;li&gt;Why use JSON Web Token&lt;/li&gt;
&lt;li&gt;When You Should Use JSON Web Token&lt;/li&gt;
&lt;li&gt;The Structure of JSON Web Token&lt;/li&gt;
&lt;li&gt;&lt;a href="//#setting-up-json-web-token-in-a-node.js"&gt;Setting Up JSON Web Token in a Node.js Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//#using-json-web-token-with-a-node.js"&gt;Using JSON Web Token with a Node.js Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//#securing-routes-with-json-web-token-in-a-node.js-application"&gt;Securing Routes with JSON Web Token in a Node.js Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Introduction to JSON Web Token
&lt;/h2&gt;

&lt;p&gt;What's up, techies? 👋In this guide, we are going to explore the magic of JSON Web Tokens (JWT) and how they can make your authentication process secured. Buckle up,and get ready to implement robust authentication in your Node.js apps. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JSON Web Token
&lt;/h2&gt;

&lt;p&gt;JSON Web Token (JWT) is a compact and self-contained way to securely transmit information between parties as a JSON object. It is an open standard (RFC 7519) that ensures the information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (HMAC) or a public/private key pair (RSA or ECDSA).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use JSON Web Token
&lt;/h2&gt;

&lt;p&gt;JWT is stateless, meaning they don't require server-side session storage, making them highly scalable. They provide a secure way to transmit information and can be easily verified. JWT are also versatile, working well for authentication, authorization, and information exchange in web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  When You Should Use JSON Web Token
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JWT are ideal for authorization. Once logged in, users can access routes, services, and resources with their JWT. Single Sign-On (SSO) commonly uses JWT due to its small overhead and cross-domain capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Information Exchange&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JWT securely transmit information between parties. With digital signatures, you can verify the sender's identity and ensure the content has not been tampered with.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Structure of JSON Web Token
&lt;/h2&gt;

&lt;p&gt;JWT consists of three parts separated by dots (.):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Header&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Specifies the token type (JWT) and signing algorithm (e.g., HS256). Encoded in Base64Url.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "alg": "HS256",
  "typ": "JWT"
}

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Payload&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Contains claims about an entity (usually the user). There are three types of claims:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Registered claims&lt;/strong&gt;&lt;/em&gt;: Predefined, optional claims like iss (issuer), exp (expiration), sub (subject), and aud (audience).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Public claims&lt;/strong&gt;&lt;/em&gt;: Custom claims defined in the IANA JWT Registry or as a URI to avoid collisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Private claims&lt;/strong&gt;&lt;/em&gt;: Custom claims agreed upon by parties using the token.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

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

&lt;/div&gt;



&lt;p&gt;3.&lt;strong&gt;Signature&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Verifies the token's integrity. Created using the encoded header, encoded payload, a secret, and the specified algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

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

&lt;/div&gt;



&lt;p&gt;The resulting JWT looks like this: &lt;code&gt;xxxxx.yyyyy.zzzzz.&lt;/code&gt; This format is compact and easily used in web environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up JSON Web Token in a Node.js Application
&lt;/h2&gt;

&lt;p&gt;Before we dive into implementing JSON Web Tokens (JWT) in your Node.js application, let's start with the basics, &lt;em&gt;installation&lt;/em&gt;. To get started with JWT, you will need to install the jsonwebtoken package. This library will help you create, sign, and verify JWTs in your application.&lt;/p&gt;

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

&lt;p&gt;First, you need to install the jsonwebtoken package using npm. Run the following command in your Node.js project directory&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install jsonwebtoken&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will add the jsonwebtoken package to your project's dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we have JWT installed, we are ready to implement it in our Node.js application. In the next section, we will cover how to use JSON Web Tokens for user authentication, including creating and verifying tokens using instance methods. Stay tuned!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Using JSON Web Token with a Node.js Application
&lt;/h2&gt;

&lt;p&gt;I know this article is not about Mongoose, schemas, and models, but to effectively implement JSON Web Tokens (JWT) in our Node.js application, we will need to touch on these concepts briefly. Let's assume you have already set up your schema logic using Mongoose. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const mongoose = require('mongoose');
const Schema = mongoose.Schema;


const UserSchema = new Schema({
  name: {
    type: String,
    required: [true, "Please insert your name"],
    minLength: [3, "Your name is too short"],
  },
  email: {
    type: String,
    required: [true, "Please insert your email"],
    match: [
      /^(([^&amp;lt;&amp;gt;()[\]\\.,;:\s@"]+(\.[^&amp;lt;&amp;gt;()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
    ],
    unique: true,
  },
  password: {
    type: String,
    required: [true, "Please insert  password"],
    minLength: [8, "Password is less than 8 character"],
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will focus on creating a JWT using an instance method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a JSON Web Token Using an Instance Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To start, we will create an instance method in our Mongoose model that will generate a JWT for a user. This instance method will be defined in the file where we have our model logic based on Mongoose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const jwt = require("jsonwebtoken");


const UserSchema = new Schema({
  // your schema logic code
});

UserSchema.methods.createToken = function () {
  return jwt.sign(
    { userId: this._id, userName: this.name },
    process.env.SECRET,
    { expiresIn: process.env.JWT_LIFETIME }
  );
};

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We assume your schema for example my case UserSchema is already defined in your Mongoose model.
We add an instance method &lt;strong&gt;createToken ** to the UserSchema. This method uses **jwt.sign&lt;/strong&gt; to create a token with the &lt;strong&gt;user's&lt;/strong&gt; &lt;strong&gt;ID&lt;/strong&gt; and &lt;strong&gt;name ** as **payload&lt;/strong&gt;, a &lt;strong&gt;secret key&lt;/strong&gt; from environment variables, and an &lt;strong&gt;expiration time&lt;/strong&gt; also from environment variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This instance method can be called on any user document to generate a JWT, making it easy to handle user authentication in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating JWT with Login and Registration
&lt;/h2&gt;

&lt;p&gt;Now that we have the instance method to create JWTs, let us see how we can use it in the login and registration logic of our Node.js application. Here is how you can integrate the createToken method:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User registration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During user registration, once the user is successfully created, we can generate a JWT and send it back to the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const UserModel = require("../models/User");
const { StatusCodes } = require("http-status-codes");
const { BadRequestError, UnauthenticatedError } = require("../errors");

const register = async (req, res) =&amp;gt; {
  const { name, email, password } = req.body;

  // Create a new user
  const user = await UserModel.create({ ...req.body });

  // Generate a JWT
  const token = user.createToken();

  // Respond with the user name and token
  res.status(StatusCodes.CREATED).json({ user: { name: user.getName() }, token });
};

module.exports = {
  register,
};

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;User login&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For user login, after validating the user's credentials, we can generate a JWT and send it back to the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const UserModel = require("../models/User");
const { StatusCodes } = require("http-status-codes");
const { BadRequestError, UnauthenticatedError } = require("../errors");

const login = async (req, res) =&amp;gt; {
  const { email, password } = req.body;

  // Validate the request
  if (!email || !password) {
    throw new BadRequestError("Please provide email and password");
  }

  // Find the user by email
  const userLogin = await UserModel.findOne({ email });

  // If user is not found
  if (!userLogin) {
    throw new UnauthenticatedError("Invalid credentials");
  }

  // Check if the password is correct
  const isPasswordCorrect = await userLogin.comparePassword(password);

  // If the password is incorrect
  if (!isPasswordCorrect) {
    throw new UnauthenticatedError("Invalid credentials");
  }

  // Generate a JWT
  const token = userLogin.createToken();

  // Respond with the user name and token
  res.status(StatusCodes.OK).json({ user: { name: userLogin.getName() }, token });
};

module.exports = {
  login,
};

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

&lt;/div&gt;



&lt;p&gt;In these examples, after a user registers or logs in successfully, we generate a JWT using the &lt;strong&gt;createToken&lt;/strong&gt; instance method and send it back in the response. This token can then be used by the client to authenticate subsequent requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the instance method in place and integrated into your login and registration logic, you can now secure your routes and verify tokens in your Node.js application. In the following section, we will cover how to use this token for  securing routes. Stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Securing Routes with JSON Web Token in a Node.js Application
&lt;/h2&gt;

&lt;p&gt;With our JWT creation logic in place, the next step is to secure our routes. To do this, we will create a file to store our authentication logic and use it as middleware in our application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating Middleware for Securing Routes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will create a middleware function that will verify the JWT in incoming requests. This middleware will check the authorization header, verify the token, and attach the user information to the request object if the token is valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const UserModel = require("../models/User");
const jwt = require("jsonwebtoken");
const { UnauthenticatedError } = require("../errors");

const auth = async (req, res, next) =&amp;gt; {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    throw new UnauthenticatedError("Authentication invalid");
  }

  const token = authHeader.split(" ")[1];

  try {
    const payload = jwt.verify(token, process.env.SECRET);
    req.user = { userId: payload.userId };
    next();
  } catch (err) {
    console.log(err);
    throw new UnauthenticatedError("Authentication invalid");
  }
};

module.exports = auth;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using the Middleware&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our authentication middleware, we can use it to secure our routes in various ways. Here are three different ways to apply the middleware:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Applying Middleware to Specific Routes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const { getUserInfo } = require('../controllers/userController');

router.get('/user-info', auth, getUserInfo);

module.exports = router;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Applying Middleware to All Routes in a Router&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const { getUserInfo, getJobs } = require('../controllers/userController');

router.use(auth);

router.get('/user-info', getUserInfo);
router.get('/jobs', getJobs);

module.exports = router;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Applying Middleware in the Main File&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const app = express();
const auth = require('./middleware/auth');
const jobRoutes = require('./routes/jobRoutes');

app.use("/api/v1/jobs", auth, jobRoutes);

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

&lt;/div&gt;



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

&lt;p&gt;In this article, we covered the basics of JSON Web Tokens (JWT) and how to use them in a Node.js application. We discussed what JWT is, why and when to use it, and how to implement it for user authentication. We also looked at securing routes using middleware in different ways. With these steps, you can enhance the security of your Node.js applications by ensuring only authenticated users can access protected resources.&lt;/p&gt;

&lt;p&gt;For more detailed information on JSON Web Tokens, you can visit the &lt;a href="https://jwt.io/introduction" rel="noopener noreferrer"&gt;jsonwebtoken documentation&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>node</category>
      <category>jsonwebtoken</category>
    </item>
    <item>
      <title>How to Use Bcrypt for Password Hashing in Node.js</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Mon, 01 Jul 2024 04:43:28 +0000</pubDate>
      <link>https://dev.to/mbugua70/how-to-use-bcrypt-for-password-hashing-in-nodejs-1l7e</link>
      <guid>https://dev.to/mbugua70/how-to-use-bcrypt-for-password-hashing-in-nodejs-1l7e</guid>
      <description>&lt;h2&gt;
  
  
  Page Content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Bcrypt&lt;/li&gt;
&lt;li&gt;Getting Started with Bcrypt&lt;/li&gt;
&lt;li&gt;Using Bcrypt with Mongoose Pre Save Middleware&lt;/li&gt;
&lt;li&gt;Implementing Password Comparison with Instance Methods in a Nodejs and Mongoose Application&lt;/li&gt;
&lt;li&gt;Password Verification in Nodejs Using Bcrypt with Mongoose Instance Methods&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction to Bcrypt
&lt;/h2&gt;

&lt;p&gt;Securing user data has become paramount, and one of the most critical aspects of this security is password protection. This is where password hashing comes into play.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Password hashing:&lt;/strong&gt; is a process of transforming a plain text password into a fixed length string of characters, which is typically a cryptographic hash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bcrypt:&lt;/strong&gt; A library to help you hash passwords.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with Bcrypt
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkch2h1a058usjm9dcqcd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkch2h1a058usjm9dcqcd.gif" alt="Let's get started" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start using bcrypt in your Node.js application, you first need to install it. Below are the instructions for installing bcrypt:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install bcrypt&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Bcrypt with Mongoose Pre-Save Middleware
&lt;/h2&gt;

&lt;p&gt;In this section, we will explore how to use bcrypt with Mongoose pre save middleware to securely hash passwords before saving them to the database. This approach ensures that plain text passwords are never stored in the database, enhancing the security of your Node.js application.&lt;/p&gt;

&lt;p&gt;Before we begin, make sure you have installed both mongoose and bcrypt in your project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install mongoose bcrypt&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing required modules
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pre save middleware is a function that runs before a document is saved to the database. This  method it is an important way to hash the user's password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pre save middleware
UserSchema.pre("save", async function () {
  //    hashing the password
  const salt = await bcrypt.genSalt(15);
  this.password = await hash(this.password, salt);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing Password Comparison with Instance Methods in a Node.js and Mongoose Application
&lt;/h2&gt;

&lt;p&gt;In this section, we will discuss how to use instance methods in Mongoose to compare passwords using bcrypt. This approach is particularly useful for verifying user credentials during the login process. Here is the code for the instance method, followed by an explanation of how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UserSchema.methods.comparePassword = async function (mainpassword) {
  return await bcrypt.compare(mainpassword, this.password);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Instance Method Definition&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;UserSchema.methods.comparePassword&lt;/em&gt;: This line defines a new instance method called comparePassword on the Mongoose schema UserSchema. Instance methods are functions that operate on individual documents  &lt;em&gt;instances&lt;/em&gt; of the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Async Function&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;em&gt;async function (mainpassword) { ... }&lt;/em&gt; : The method is defined as an asynchronous function that takes mainpassword as an argument. mainpassword represents the plain text password that needs to be compared with the stored hashed password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Password Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;return await bcrypt.compare(mainpassword, this.password);&lt;/em&gt; : This line uses bcrypt  compare function to compare the provided plain text password &lt;strong&gt;mainpassword&lt;/strong&gt; with the hashed password stored in the current document &lt;strong&gt;this.password&lt;/strong&gt; . The compare function returns a promise that resolves to true if the passwords match and false otherwise.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Password Verification in Node.js Using Bcrypt with Mongoose Instance Methods
&lt;/h2&gt;

&lt;p&gt;In this section, we will focus on how to use the &lt;strong&gt;comparePassword&lt;/strong&gt; instance method within the login logic of a Node.js application to securely verify user passwords using bcrypt. Please note that the validation and error handling in this example are not the primary focus and are included for completeness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const login = async (req, res) =&amp;gt; {
  const { email, password } = req.body;

  //   validation
  if ((!email, !password)) {
    throw new BadRequestError("Please provide email and password");
  }

  const userLogin = await UserModel.findOne({ email });

  if (!userLogin) {
    throw new UnauthenticatedError("Invalid credentials");
  }

  const isPasswordCorrect = await userLogin.comparePassword(password);

  if (!isPasswordCorrect) {
    throw new UnauthenticatedError("Invalid credentials");
  }

  const token = userLogin.createToken();
  res
    .status(StatusCodes.OK)
    .json({ user: { name: userLogin.getName() }, token });
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation of comparePassword Usage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Finding the User&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The code first retrieves the user document from the database using &lt;code&gt;UserModel.findOne({ email })&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the user is not found, it throws an error indicating invalid credentials.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Comparing Passwords&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const isPasswordCorrect = await userLogin.comparePassword(password);&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This line uses the &lt;strong&gt;comparePassword&lt;/strong&gt;  instance method defined on the user schema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The method compares the provided plain text password &lt;strong&gt;password&lt;/strong&gt;  with the hashed password stored in the database &lt;em&gt;userLogin.password&lt;/em&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;comparePassword&lt;/em&gt;  uses &lt;em&gt;bcrypt&lt;/em&gt;  compare function/method and returns true if the passwords match, or false otherwise.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Handling Incorrect Passwords&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the password comparison fails  &lt;em&gt;!isPasswordCorrect&lt;/em&gt; , an error is thrown indicating invalid credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generating and Returning a Token&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the password comparison succeeds, a token is generated using &lt;em&gt;userLogin.createToken()&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The response includes the user name and the generated token&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In this article, we explored how to use &lt;a href="https://www.npmjs.com/package/bcrypt" rel="noopener noreferrer"&gt;bcrypt&lt;/a&gt; in a &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; application with &lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; to securely hash and verify passwords. We covered the installation of &lt;a href="https://www.npmjs.com/package/bcrypt" rel="noopener noreferrer"&gt;bcrypt&lt;/a&gt;, the implementation of password hashing using &lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; pre save middleware, and the use of &lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; instance methods for password comparison during login. By following these steps, you can enhance the security of your application authentication system, ensuring that user passwords are properly protected. &lt;/p&gt;

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

</description>
      <category>node</category>
      <category>mongodb</category>
      <category>mongoose</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Getting Started with Mongoose</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Fri, 28 Jun 2024 10:35:35 +0000</pubDate>
      <link>https://dev.to/mbugua70/getting-started-with-mongoose-150h</link>
      <guid>https://dev.to/mbugua70/getting-started-with-mongoose-150h</guid>
      <description>&lt;h2&gt;
  
  
  PAGE CONTENT
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Mongoose&lt;/li&gt;
&lt;li&gt;Connecting to the database&lt;/li&gt;
&lt;li&gt;Creating Models and Schemas.&lt;/li&gt;
&lt;li&gt;Using Your Model in Controller Functions.&lt;/li&gt;
&lt;li&gt;Conclusion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction to Mongoose
&lt;/h2&gt;

&lt;p&gt;Mongoose is an ODM (Object Data Modeling) library designed to streamline the interaction between your MongoDB database and Node.js applications.It is designed to work with asynchronous environments and offers a powerful set of features that simplify data manipulation and validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to the database
&lt;/h2&gt;

&lt;p&gt;Before diving into Mongoose, you need to establish a connection to your MongoDB database. Here’s a step-by-step guide to get you started:&lt;/p&gt;

&lt;h3&gt;
  
  
  1.Installing Mongoose
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npm install mongoose&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Importing Mongoose and creating a connection file
&lt;/h3&gt;

&lt;p&gt;Create a file called &lt;em&gt;connect.js&lt;/em&gt; and place the connection logic there. This function returns a promise, which allows you to handle the connection success or failure in your main file.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//connect.js
const mongoose = require('mongoose')

const connectDB = (url) =&amp;gt; {
  return mongoose.connect(url)
}

module.exports = connectDB

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Use the Connection in Your Main File:
&lt;/h3&gt;

&lt;p&gt;In your main application file for example &lt;em&gt;app.js&lt;/em&gt;, import and use the connection logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//app.js
require('dotenv').config();
const express = require('express');
const app = express();

// connectdb
const connectDB = require("./db/connect"); //Add the path to the connection logic file.

// Get the MongoDB connection string from environment variables
const MONGODB_STRING = process.env.MONGODB_STRING;

app.get("/", (req, res) =&amp;gt; {
  res.send("Hello Heroku app");
});


const port = process.env.PORT || 4040;

// Function to start the server
const start = async () =&amp;gt; {
  try {
    // Connect to the database. Pass the MongoDB String as an arguement of the connectDB function.
    await connectDB(MONGODB_STRING)
    app.listen(port, () =&amp;gt;
      console.log(`Connected to the database and listening on port ${port}...`)
    );
  } catch (error) {
    console.log(error);
  }
};

start();

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Environment Variables: Use dotenv to load &lt;em&gt;MONGODB_STRING&lt;/em&gt; and 
&lt;em&gt;PORT&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Database Connection: connectDB in &lt;em&gt;db/connect.js&lt;/em&gt; in my case returns 
a promise for 
the database connection.&lt;/li&gt;
&lt;li&gt;Async/Await: Use async/await in app.js to ensure the server starts 
only after a successful database connection.&lt;/li&gt;
&lt;li&gt;Error Handling: Handle connection errors with a try/catch block.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating Models and Schemas
&lt;/h2&gt;

&lt;p&gt;In Mongoose, models and schemas are fundamental for defining and interacting with data in MongoDB.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema&lt;/strong&gt;: Defines the structure of your data. It specifies the shape that each document (instance) will have in the database. Think of it as a blueprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Once you have a schema, you compile it into a model. A model is a JavaScript class that represents a collection in MongoDB. It is responsible for creating and reading documents from the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document&lt;/strong&gt;: An instance of a model is called a document. Each document is a record in your MongoDB collection, based on the schema you defined.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a file called &lt;em&gt;job.js&lt;/em&gt; and place to place your logic there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const JobSchema = new Schema(
  {
    company: {
      type: String,
      required: [true, "Please the field can't be empty"],
    },
    position: {
      type: String,
      required: [true, "Please the field can't be empty"],
    },
    status: {
      type: String,
      required: [true, "Please the field can't be empty"],
      enum: ["interview", "declined", "pending", "accepted"],
      default: "pending",
    },

  },
  { timestamps: true }
);

const JobModel = mongoose.model("Job", JobSchema);

module.exports = JobModel;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Schema Definition: *&lt;em&gt;JobSchema *&lt;/em&gt; defines fields &lt;em&gt;company&lt;/em&gt;, &lt;em&gt;position&lt;/em&gt;, &lt;em&gt;status _ and their types. It includes validations (required, enum) and a default value _default&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Model Creation: *&lt;em&gt;JobModel *&lt;/em&gt; is created using mongoose.model(), linking Job as the collection name in MongoDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Your Model in Controller Functions
&lt;/h2&gt;

&lt;p&gt;In an Express application using Mongoose, it's common to separate your model definitions from your controller logic. This promotes modularity and improves code organization. So you can create a file and place your logic there for controller functions. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Controller Functions&lt;/strong&gt;: These functions &lt;em&gt;getAllJobs&lt;/em&gt;, &lt;em&gt;createJob&lt;/em&gt;, &lt;em&gt;getJob&lt;/em&gt;, &lt;em&gt;updateJob&lt;/em&gt;, &lt;em&gt;deleteJob&lt;/em&gt; handle CRUD operations for jobs. They interact with the imported (JobModel) to perform database operations based on HTTP requests.&lt;/li&gt;
&lt;li&gt;You will export this controller function and map them to the routes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const JobModel = require("../models/Job");
const { StatusCodes } = require("http-status-codes");
const { BadRequestError, NotFoundError } = require("../errors/bad-request");

const getAllJobs = async (req, res) =&amp;gt; {

  const jobs = await JobModel.find({ createdBy: req.user.userId });
  res.status(StatusCodes.CREATED).json({ jobs });
};

const createJobs = async (req, res) =&amp;gt; {
  req.body.createdBy = req.user.userId;
  const jobs = await JobModel.create(req.body);

  res.status(StatusCodes.CREATED).json({ jobs });
};

const getJob = async (req, res) =&amp;gt; {
  const {
    user: { userId },
    params: { id: job_id },
  } = req;

  const job = await JobModel.findOne({ _id: job_id, createdBy: userId });
  if (!job) {
    throw new NotFoundError(`No job with id: ${job_id}`);
  }

  res.status(StatusCodes.OK).json({ job });
};

const updateJob = async (req, res) =&amp;gt; {
  const {
    body: { company, position },
    params: { id: job_id },
    user: { userId },
  } = req;

  if (company === "" || position === "") {
    throw new BadRequestError("company and position cannot be found");
  }

  const job = await JobModel.findByIdAndUpdate(
    { _id: job_id, createdBy: userId },
    req.body,
    { new: true, runValidators: true }
  );

  res.status(StatusCodes.OK).json({ job });
};

const deleteJob = async (req, res) =&amp;gt; {
  const {
    params: { id: job_id },
    user: { userId },
  } = req;

  const job = await JobModel.findByIdAndDelete({
    _id: job_id,
    createdBy: userId,
  });

  if (!job) {
    throw new NotFoundError(`No user with id: ${job_id}`);
  }

  res.status(StatusCodes.OK).json({ msg: "Job deleted successfully" });
};

module.exports = {
  getAllJobs,
  createJobs,
  getJob,
  updateJob,
  deleteJob,
};

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Import Controller Functions:
&lt;/h3&gt;

&lt;p&gt;Import controller functions &lt;em&gt;getAllJobs&lt;/em&gt;, &lt;em&gt;createJob&lt;/em&gt;, &lt;em&gt;getJob&lt;/em&gt;, &lt;em&gt;updateJob&lt;/em&gt;, &lt;em&gt;deleteJob&lt;/em&gt;  from the path your controller function login is located.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mapping Routes: Each HTTP method &lt;em&gt;GET&lt;/em&gt;, &lt;em&gt;POST&lt;/em&gt;, &lt;em&gt;PUT&lt;/em&gt;, &lt;em&gt;DELETE&lt;/em&gt; is mapped to its corresponding controller function &lt;em&gt;getAllJobs&lt;/em&gt;, &lt;em&gt;createJob&lt;/em&gt;, &lt;em&gt;getJob&lt;/em&gt;, &lt;em&gt;updateJob&lt;/em&gt;, &lt;em&gt;deleteJob&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const router = express.Router();
const auth = require("../middleware/authentication");

const {
  getAllJobs,
  getJob,
  createJobs,
  updateJob,
  deleteJob,
} = require("../controllers/jobs");

router.use(auth);
router.route('/').get(getAllJobs).post(createJobs);
router.route('/:id').get(getJob).patch(updateJob).delete(deleteJob);


module.exports = router;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Importing your router in your main file.
&lt;/h3&gt;

&lt;p&gt;In an Express application, routers are used to organize and handle different sets of routes. Here is how you integrate a router into your main application file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import the router in your main file (app.js)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;const jobRoutes = require("./routes/jobs");&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Applying Router Middleware in your main file (app.js)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//app.js
require('dotenv').config();
const express = require('express');
const app = express();

//imported router
const jobRoutes = require("./routes/jobs");
// connectdb
const connectDB = require("./db/connect"); //Add the path to the connection logic file.

// Get the MongoDB connection string from environment variables
const MONGODB_STRING = process.env.MONGODB_STRING;

app.get("/", (req, res) =&amp;gt; {
  res.send("Hello Heroku app");
});


const port = process.env.PORT || 4040;

// Function to start the server
const start = async () =&amp;gt; {
  try {
    // Connect to the database. Pass the MongoDB String as an arguement of the connectDB function.
    await connectDB(MONGODB_STRING)
    app.listen(port, () =&amp;gt;
      console.log(`Connected to the database and listening on port ${port}...`)
    );
  } catch (error) {
    console.log(error);
  }
};

start();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Integrating Mongoose in Node.js simplifies MongoDB interactions through schema based modeling, enhancing data structure and validation. Explore more in the &lt;a href="//mongoosejs.com"&gt;mongoosejs.com&lt;/a&gt; official documentation. &lt;/p&gt;

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

</description>
      <category>mongoose</category>
      <category>node</category>
      <category>mongodb</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Getting started with Git and Github</title>
      <dc:creator>john mbugua</dc:creator>
      <pubDate>Sat, 30 Apr 2022 15:45:52 +0000</pubDate>
      <link>https://dev.to/mbugua70/getting-started-with-git-and-github-3mg</link>
      <guid>https://dev.to/mbugua70/getting-started-with-git-and-github-3mg</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;h2&gt;
  
  
  version control
&lt;/h2&gt;

&lt;p&gt;Version control is also known as revision control /source control is a class of systems responsible for managing changes to your files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of version control system
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Centralize version control systems&lt;/li&gt;
&lt;li&gt;Distributed version control systems&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Centralized version control system
&lt;/h3&gt;

&lt;p&gt;CVCS have only one central repository. Repository is basically a server which all the file and history are stored. The machine can access the repository via LAN and WAN.&lt;/p&gt;

&lt;p&gt;Example of CVCS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Concurrent version system (CVS)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Subversion (SVN)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  Distributed version control system
&lt;/h3&gt;

&lt;p&gt;DVCS don't require a central server that contain repository. Every user has its own repository called &lt;em&gt;local repository&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Example of DVCS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GIT&lt;/li&gt;
&lt;li&gt;Bit-keeper&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  What is git ?
&lt;/h3&gt;

&lt;p&gt;GIT is a decentralized version control system used to keep changes of your file.&lt;/p&gt;

&lt;p&gt;GIT was developed by &lt;em&gt;Linus Torvalds&lt;/em&gt; in 2005 for efficient code management and version control of their project. Understanding basic commands of git could help you in storing your projects in your local repository and pushing them into your remote repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Git installation
&lt;/h3&gt;

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

&lt;p&gt;&lt;a href="https://git-scm.com/download/win" rel="noopener noreferrer"&gt;Download git for windows&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://git-scm.com/download/mac" rel="noopener noreferrer"&gt;Download git for mac&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.Linux (Debian)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$sudo apt-get install git&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Git commands
&lt;/h3&gt;

&lt;p&gt;The following are basics commands of git.&lt;/p&gt;

&lt;h3&gt;
  
  
  git config
&lt;/h3&gt;

&lt;p&gt;This command is used to set user configuration such as user-name and user-email as shown below:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git init
&lt;/h3&gt;

&lt;p&gt;This is one of the common git command you will be using. Its used to initialize local git repository.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git add
&lt;/h3&gt;

&lt;p&gt;The command &lt;strong&gt;git add&lt;/strong&gt; is used to add the file into local repository for example below the &lt;em&gt;.index&lt;/em&gt; will be added to local repository:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git status
&lt;/h3&gt;

&lt;p&gt;This &lt;strong&gt;git status&lt;/strong&gt; command is used to check status of working tree. Below you see three file which are untracked:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git commit
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;git commit&lt;/strong&gt; command is used to commit in the staging area. The committed changes will now go to remote repository. Example:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git push
&lt;/h3&gt;

&lt;p&gt;Once the files have been committed the &lt;strong&gt;git push&lt;/strong&gt; command is used to push the files to remote repositories:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git pull
&lt;/h3&gt;

&lt;p&gt;The command &lt;strong&gt;git pull&lt;/strong&gt; is used to fetch/merge content in remote repository into local repository:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  git clone
&lt;/h3&gt;

&lt;p&gt;This command is used to download existing git repository into your local repository. For example below the &lt;strong&gt;git clone&lt;/strong&gt; command will download the files from existing remote repository to local repository(basics of git):&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git rm
&lt;/h3&gt;

&lt;p&gt;The command &lt;strong&gt;git rm&lt;/strong&gt; will delete or remove the file from repository: Below we can see the file &lt;em&gt;.index&lt;/em&gt; removed:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git branch
&lt;/h3&gt;

&lt;p&gt;This command is used to create a new branch. Example &lt;strong&gt;git branch&lt;/strong&gt; will create new branch called myapp:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git checkout
&lt;/h3&gt;

&lt;p&gt;This command help you to navigate from one branch to another. Example we used &lt;strong&gt;git checkout&lt;/strong&gt; to navigate from &lt;em&gt;master&lt;/em&gt; branch to &lt;em&gt;myapp&lt;/em&gt; branch:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  git merge
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;git merge&lt;/strong&gt; is used to integrate two branches together. It will merge one branch to another active branch. Below we have merge &lt;em&gt;myapp&lt;/em&gt; to &lt;em&gt;master&lt;/em&gt; branch:&lt;/p&gt;

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

</description>
      <category>git</category>
      <category>github</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
