<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Aron Berezkin</title>
        <link>https://aronberezkin.com</link>
        <description>Personal blog focused on practical React Native tutorials and my career change to become a frontend developer</description>
        <lastBuildDate>Sun, 24 Nov 2024 08:52:28 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Aron Berezkin</title>
            <url>https://www.aronberezkin.com/_next/image?url=%2Fimages%2FprofileRect.png&amp;w=750&amp;q=75</url>
            <link>https://aronberezkin.com</link>
        </image>
        <copyright>CC BY-NC 4.0 2024 @ Aron Berezkin</copyright>
        <item>
            <title><![CDATA[A Step By Step Guide To Writing Your First Expo Config Plugin]]></title>
            <link>/posts/a-step-by-step-guide-to-writing-your-first-expo-config-plugin</link>
            <guid>/posts/a-step-by-step-guide-to-writing-your-first-expo-config-plugin</guid>
            <pubDate>Tue, 30 Nov 2021 08:00:00 GMT</pubDate>
            <description><![CDATA[Frustrated when your managed Expo project misbehaves and you have no option to customize it? Well, that is a thing of the past now. This tutorial will teach you how to start with Expo config plugins.]]></description>
            <content:encoded><![CDATA[<h1 id="a-step-by-step-guide-to-writing-your-first-expo-config-plugin">A STEP BY STEP GUIDE TO WRITING YOUR FIRST EXPO CONFIG PLUGIN</h1>
<p>Frustrated when your managed Expo project misbehaves and you have no option to customize it? Well, that is a thing of the past now. This tutorial will teach you how to start with Expo <a href="https://docs.expo.dev/guides/config-plugins/">config plugins</a> which allow you to add custom native Android and iOS configurations without ejecting the managed workflow. We will use a practical example by debugging and fixing Android&#39;s status bar translucent behavior to allow our splash screen reach all device edges.</p>
<h2 id="initial-setup">INITIAL SETUP</h2>
<p>To initiate our project you can simply clone <a href="https://github.com/AronBe/article-first-config-plugin">this repository</a> that has all demonstrative assets included. Or you can start yourself by running expo-cli:</p>
<pre><code class="language-sh">expo init first-config-plugin -t expo-template-blank-typescript
</code></pre>
<p>Then add <a href="https://docs.expo.dev/versions/latest/sdk/splash-screen/">expo-splash-screen</a> as your dependency..</p>
<pre><code class="language-sh">expo install expo-splash-screen
</code></pre>
<p>..and necessary assets to reproduce the issue. We are using typescript for better development experience, which you will definitely find it helpful writing the plugins.</p>
<h2 id="the-issue">THE ISSUE</h2>
<p>We want our application to look cool and therefore we show a full screen image on the intro page. For that we need to set the status bar to be <code>translucent</code> so that image can stretch under it.</p>
<pre><code class="language-jsx">&lt;StatusBar style=&quot;dark&quot; translucent backgroundColor=&quot;transparent&quot; /&gt;
</code></pre>
<p>The issue is that the status bar is not translucent from the start, resulting in our splash screen and logo shifting up once the translucency takes effect on the app mount. Notice also the color shift of the status bar.</p>
<video width="320" controls>
<source src="/video/statusBarNotTranslucent.mp4" type="video/mp4" />
</video>

<p>Luckily Expo allows us to configure the Android status bar through <a href="https://docs.expo.dev/versions/latest/config/app/#androidstatusbar">app.json</a> which will set the default behavior before the app mounts. Lets try to replicate our settings:</p>
<pre><code class="language-json">  &quot;androidStatusBar&quot;: {
      &quot;backgroundColor&quot;: &quot;#00000000&quot;,
      &quot;barStyle&quot;: &quot;dark-content&quot;,
      &quot;translucent&quot;: true
    }
</code></pre>
<p>The result is not exactly what we wanted. While we managed to make the color of status bar dark from the app launch and logo is not shifting up anymore as translucency is taking effect, the bar itself has that ugly overlay.</p>
<video width='320px'  controls>
<source src="/video/statusBarTranslucent.mp4" type="video/mp4" />
</video>

<p>We need to investigate what is going on. By running <code>expo run:android</code> or <code>expo prebuild -p android</code> we can generate the Android folder with its configurations. If you don&#39;t know where the issue is coming from, you can use a simple strategy to see where changes are being made. Just stage all generated Android files (<code>git add -A</code>), remove <code>translucent: true</code> from app.json, and run <code>expo prebuild -p android</code> to generate native files again.</p>
<p>By removing the translucent property you should see following unstaged changes:</p>
<p><strong>android/app/src/main/res/values/strings.xml</strong></p>
<pre><code class="language-xml">- &lt;string name=&quot;expo_splash_screen_status_bar_translucent&quot; translatable=&quot;false&quot;&gt;true&lt;/string&gt;
+ &lt;string name=&quot;expo_splash_screen_status_bar_translucent&quot; translatable=&quot;false&quot;&gt;false&lt;/string&gt;
</code></pre>
<p><strong>android/app/src/main/res/values/styles.xml</strong></p>
<pre><code class="language-xml">- &lt;item name=&quot;android:windowTranslucentStatus&quot;&gt;true&lt;/item&gt;
</code></pre>
<p>This already looks promising as the <code>expo_splash_screen_status_bar_translucent</code> custom Expo property sounds exactly like something we are trying to influence and being previously <code>true</code> we saw the status bar was really translucent during the splash screen. We also notice that <code>android:windowTranslucentStatus</code> was set to <code>true</code> which with some googling we realize was responsible for the status bar overlay. If you are in managed workflow, in the past you would feel trapped because you can&#39;t have one without the other to reach the behavior you wanted and the only option was to raise it in Expo <a href="https://github.com/expo/expo/issues/11604#issuecomment-964953312">issues</a>. But now thanks to Expo config plugins you can take the solution in your hands.</p>
<h2 id="the-solution">THE SOLUTION</h2>
<p>The solution is to make <code>expo_splash_screen_status_bar_translucent</code> set to <code>true</code> while keeping <code>android:windowTranslucentStatus</code> as <code>false</code> - which is the default therefore lets change only the Expo property. With <code>expo run:android</code> you can actually change it in your Android native files yourself to prove the effect after a new build. Yet if we want to stay in managed workflow and away from native file changes, we need to write a custom plugin which will do the change for us during the prebuild.</p>
<blockquote>
<p>This means any native changes through plugins will be reflected in Expo development environment only using <a href="https://docs.expo.dev/development/getting-started/">expo-dev-client</a> - our custom Expo Go.</p>
</blockquote>
<p>The <code>@expo/config-plugins</code> package is already part of Expo, so we don&#39;t need to install any new dependency. We will start by creating our plugin file in typescript, which is a recommended approach and can be useful not only for more advanced changes.</p>
<p>Lets create our initial plugin file <code>withAndroidSplashScreen.ts</code> in the root folder:</p>
<pre><code class="language-ts">import type { ConfigPlugin } from &#39;@expo/config-plugins&#39;
import { withStringsXml } from &#39;@expo/config-plugins&#39;

const withAndroidSplashScreen: ConfigPlugin = (expoConfig) =&gt;
  withStringsXml(expoConfig, (modConfig) =&gt; {
    return modConfig
  })

export default withAndroidSplashScreen
</code></pre>
<p>And start compiling it into javascript:</p>
<pre><code class="language-sh">yarn tsc withAndroidSplashScreen.ts --watch --skipLibCheck
</code></pre>
<p>Finally, import resulting <code>withAndroidSplashScreen.js</code> file into app.json <code>plugins</code> property for Expo to process it on a next build. Our changes look like this:</p>
<pre><code class="language-json">{
  &quot;expo&quot;: {
    ...otherProps,
    &quot;androidStatusBar&quot;: {
      &quot;backgroundColor&quot;: &quot;#00000000&quot;,
      &quot;barStyle&quot;: &quot;dark-content&quot;
    },
    &quot;plugins&quot;: [&quot;./withAndroidSplashScreen.js&quot;]
  }
}
</code></pre>
<p>Now you can run <code>expo prebuild -p android</code> to see effects of your plugin. Obviously, if you inspect our <code>withAndroidSplashScreen</code> code it is not changing anything yet. It just returns whatever it receives. Our plugin is a simple function.</p>
<p>Initially our plugin receives <code>expoConfig</code> which is basically content of <code>app.json</code> and this object is passed to the <code>withStringXml</code> mod. This particular mod (modifier) from Expo enables us to read contents of <strong>android/app/src/main/res/values/strings.xml</strong> and change them based on what config we return (all available mods can be found <a href="https://docs.expo.dev/guides/config-plugins/#mod-plugins">here</a>). For each mod its content can be read from <code>modConfig.modResults</code> - you can actually use <code>console.log(JSON.stringify(config.modResults, null, 2));</code> to inspect the values during the <code>prebuild</code> command. To apply our desired changes we need to modify <code>modResults</code>.</p>
<pre><code class="language-ts">import type { ConfigPlugin } from &#39;@expo/config-plugins&#39;
import { AndroidConfig, withStringsXml } from &#39;@expo/config-plugins&#39;

const withAndroidSplashScreen: ConfigPlugin = (expoConfig) =&gt;
  withStringsXml(expoConfig, (modConfig) =&gt; {
    modConfig.modResults = AndroidConfig.Strings.setStringItem(
      [
        {
          _: &#39;true&#39;,
          $: {
            name: &#39;expo_splash_screen_status_bar_translucent&#39;,
            translatable: &#39;false&#39;
          }
        }
      ],
      modConfig.modResults
    )
    return modConfig
  })

export default withAndroidSplashScreen
</code></pre>
<p>As you see, we assign to <code>modResults</code> what is returned from AndroidConfig helper method <code>setStringItem</code> which accepts the value we want to add and then remaining file strings already existing. Inspecting type of <code>setStringItem</code> and typescript in general should help you fill all needed properties correctly. After running <code>prebuild</code> we should see a new configuration string:</p>
<pre><code class="language-xml">+ &lt;string name=&quot;expo_splash_screen_status_bar_translucent&quot; translatable=&quot;false&quot;&gt;true&lt;/string&gt;
</code></pre>
<p>We now have our desired splash screen behavior with a translucent status bar already from the app start and without the ugly overlay.</p>
<h2 id="summary">SUMMARY</h2>
<p>Hopefully this tutorial helped you to understand better the power of config plugins and that customizing your Expo project is actually not that difficult - you can see final solution in <a href="https://github.com/AronBe/article-first-config-plugin/tree/solution">this branch</a>. If you ask what to do with the native Android folder now when you are finished with debugging, you can just delete it together with all generated files. Important is to commit your new plugin file and changes in app.json. The <code>prebuild</code> command is a part of EAS build so next time you build your project, you can be sure your plugin will take effect the same way you did it locally.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Left a Financial Markets Career for Web Development]]></title>
            <link>/posts/how-i-left-a-financial-markets-career-for-web-development</link>
            <guid>/posts/how-i-left-a-financial-markets-career-for-web-development</guid>
            <pubDate>Tue, 25 Feb 2020 08:00:00 GMT</pubDate>
            <description><![CDATA[Thinking about breaking into web development? Unsure if you have sufficient knowledge or if it's too late for you? Maybe you have a friend struggling with taking the leap. Whatever the case, my story might help.]]></description>
            <content:encoded><![CDATA[<h1 id="how-i-left-a-financial-markets-career-for-web-development">HOW I LEFT A FINANCIAL MARKETS CAREER FOR WEB DEVELOPMENT</h1>
<p>Thinking about breaking into web development? Unsure if you have sufficient knowledge or if it&#39;s too late for you? Maybe you have a friend struggling with taking the leap. Whatever the case, my story might help.</p>
<p>I studied finance &amp; investments at university for five years, then spent another five years working as an analyst for Bloomberg in London. Yet when I turned 30, I joined STRV — starting my journey as a web developer.</p>
<p>As you might guess, the path to get here wasn&#39;t clearcut. The biggest roadblock for a person changing careers is the psychological battle. Your brain can easily calculate what you&#39;re leaving behind (10 years in finance), but can&#39;t really determine what you might gain. Let&#39;s go over what to ask yourself when making this big life decision, and how to move forward.</p>
<h2 id="deciding-if-its-the-right-move">DECIDING IF IT&#39;S THE RIGHT MOVE</h2>
<p>Learning what a web developer does is the first piece of the puzzle. Obviously, the ideal situation is to know someone who actually works as a developer, and even better if that someone&#39;s also gone through a career change. If you don&#39;t personally know anyone that fits the bill, you can easily find someone at a local development meetup (use the <a href="https://www.meetup.com/">Meetup</a> app or <a href="https://www.facebook.com/events/">Facebook events</a>). You can also read about building a web development career at <a href="https://www.freecodecamp.org/">freeCodeCamp</a> or <a href="https://medium.com/">Medium</a>, watch relevant Youtube videos or listen to a podcast. I did all of that and found everything equally helpful. <strong>Remember: You&#39;re entering a very broad and fast-moving space, so one developer alone cannot provide all the necessary info.</strong></p>
<p>What intrigued me most was the lifestyle (remote work, flexible hours) and an opportunity to constantly develop myself, learn new things and build something people will find useful. If you like learning new things, this industry is for you. There are new programming technologies popping up all the time and while this can get tiring for someone who&#39;s been in the industry for years, those newer to the job find this exciting. This actually gives newbies a great advantage — <strong>companies need fresh, flexible minds that are enthusiastic and willing to learn a specific stack of technologies used</strong>.</p>
<p>As for having joined STRV, I&#39;m thrilled to have the opportunity to determine my own hours and, even more than that, it&#39;s incredible to have smart colleagues around, all of whom help me develop my coding skills and provide guidance when trying new technologies.</p>
<h2 id="ready-to-learn">READY TO LEARN?</h2>
<p>The learning process for new developers can be split into the categories below. Since we all have a different learning style, I mention both pros and cons for each category. I&#39;d recommend starting with the first category (as though it&#39;s the first step) and going from there—or choosing and combining what works for you.</p>
<h3 id="interactive-platforms">Interactive Platforms</h3>
<p>If you&#39;ve never coded before, you need to start with the basics (data structures, conditionals, loops, functions, etc.). The best way to do that is to use a free interactive coding app, such as <a href="https://www.codecademy.com/">Codecademy</a>, <a href="https://www.sololearn.com/">Sololearn</a> or freeCodecamp basic courses. They are great because <strong>you don&#39;t have to install or set anything up</strong>, which can be a demotivating headache for a beginner. Some of them have a mobile app, too.</p>
<p>The apps teach users that writing code has to be precise. For example, it&#39;s not always apparent to new developers that lower and upper case letters matter. Another revelation for beginners is the importance of conditionals, and that showing either &#39;login&#39; or &#39;logout&#39; in a navigation menu is just an if condition based on a user being logged in or not. My advice would be to use these platforms to grasp the basics before they become repetitive and lengthy, then move on to more comprehensive material.</p>
<h3 id="video-tutorials">Video Tutorials</h3>
<p>The next step involves taking more comprehensive video courses that teach how to build an app from the ground up. It is closer to reality than interactive platforms and is a good way to check if you actually enjoy the development process. <a href="https://www.udemy.com/">Udemy</a> and YouTube are great inexpensive sources to start with. Finding the right content among the vast amount of videos might be a challenge, but reviews and the number of subscribers/likes are a good guide.</p>
<p><strong>When searching for videos, finding updated content is crucial given that the technologies advance very quickly.</strong> If you use outdated content, you might encounter compatibility issues if the tutor does not specify which version of a library he/she is using.</p>
<p>Once you&#39;ve found some good options, observe the teachers and learn from those with a teaching style that suits you best. Among free content with good tutors, I recommend <a href="http://youtube.com/channel/UCJZv4d5rbIKd4QHMPkcABCw">Kevin Powell</a> (html/css), <a href="https://www.youtube.com/channel/UCW5YeuERMmlnqo4oq8vwUpg">The Net Ninja</a> (frontend) and <a href="https://www.youtube.com/channel/UC29ju8bIPH5as8OGnQzwJyA">Traversy Media</a> (various tutorials).</p>
<h3 id="motivation-inspiration-clarity">Motivation, Inspiration, Clarity</h3>
<p>Following a lengthy tutorial, you often get to a point when it&#39;s useful to step back from coding and consolidate what you&#39;ve learned. Listening to podcasts such as <a href="https://www.codenewbie.org/">CodeNewbie</a> and <a href="https://syntax.fm/">Syntax</a> or watching YouTube videos like <a href="https://www.youtube.com/watch?v=0pThnRneDjw">Web Development in 2020</a> can complement the learning process, help you keep up with the industry&#39;s new trends and guide you in what to learn next.</p>
<p>You might also find yourself battling dilemmas such as learning a programming framework (React, Vue, Angular) versus focusing more on core knowledge of vanilla JavaScript, or styling your app with pure CSS versus utilizing a design library (Bootstrap, Material UI, Tailwind). Whatever it is you&#39;re struggling to answer, <strong>focus on keeping your motivations high by remembering where you&#39;re headed: building something real and valuable.</strong></p>
<p>Furthermore, reading freeCodeCamp or Medium articles about career changes or development work also keeps you motivated and inspired. Twitter is great for this as well. And if you need more accountability, sign up for the <a href="https://twitter.com/search?q=%23100DaysOfCode&amp;src=hashtag_click">#100DaysOfCode</a> challenge to join a great community of upcoming programmers, who will support you whenever needed.</p>
<p>Content can feel repetitive after some time, especially while you haven&#39;t moved on to advanced topics yet. But personally, I loved this part of the learning process because it&#39;s — unlike when you&#39;ve moved on to actual coding and you have to find free time and really focus. With a full-time job, that usually means waking up quite early or staying up late.</p>
<h3 id="meetups-bootcamps-academies">Meetups, Bootcamps, Academies</h3>
<p>Meetups are irreplaceable. You get to know real developers who can answer any questions that pop up in your head. Sometimes, the topics might be too advanced to comprehend when you&#39;re a newbie, but give it a few months. Keep listening and learning. You&#39;ll gain a lot more clarity about standards and new trends in development. I once went to a <a href="https://jamstack.org/">Jamstack</a> meetup in London (before it became such a buzzword) and the knowledge I gained definitely helped me keep up during various conversations with other developers before officially becoming one myself.</p>
<p>Bootcamps are also a popular way to speed up the learning process, but they aren&#39;t for everyone. <strong>It depends on whether you prefer learning at your own pace or the pace set by a tutor</strong>. Bootcamps can be very intense and a bit on the expensive side, so think twice whether or not the format works for you. While another huge benefit of them is that they connect you with like-minded developers and the industry, you can do that on your own if you put in the time. So if the format does suit you, and you prefer investing money over time — go for it.</p>
<p><strong>As part of their hiring process, some development companies set up academies</strong> where they invite both developers and non-developers to attend a series of workshops. It&#39;s a great alternative to bootcamps because they are usually free, with no strings attached. You just have to show that you have the right attitude and hunger for learning. The fact that I attended <a href="https://github.com/strvcom/react-nights-2019">STRV React Nights</a> in 2019 definitely played an important role in eventually getting hired.</p>
<p>Whether you decide to go with any of these options or not, my advice is to keep asking questions. Leave all doubts behind; so what if it ends up not working out? The worst thing that can happen is that you will have spent time on learning something new.</p>
<h3 id="building-stuff">Building stuff</h3>
<p>Probably the most crucial part of the learning process is to start building stuff on your own. Here, you will question yourself the most because it is the hardest. Tutorials teach you to follow along, but taking things into your own hands and actually making calls about how to structure your project and code is a whole different ballgame. If you lose confidence, even right at the beginning, there&#39;s nothing wrong with turning to your peers or sources for inspiration. Have a look back at the tutorials you&#39;ve gone through or check out STRV&#39;s open source <a href="https://github.com/strvcom">templates</a>.</p>
<p>A big question during this time is: What do you actually build? If you come up with an idea, do it. <strong>Starting a project will be your biggest motivation</strong>. And if you&#39;re low on ideas, a good tactic is to start replicating designs of other websites, even popular ones like Twitter. <a href="https://developers.google.com/web/tools/chrome-devtools/">Google Developer Tools</a> can help to guide you.</p>
<p><strong>A good way to give purpose to your project is by adding it to your portfolio</strong>. You probably don&#39;t yet have the skills to build something that you could ask money for, so build a website for someone that needs it. It can be your friend, a small local business or a charity. When I was starting to develop, I noticed that a pastry shop near my apartment didn&#39;t have a website, so I went ahead and built a simple landing page. The plan was to first build it, then show them. Unfortunately, before I got the opportunity to present it to them, they already had one ¯_(ツ)_/¯.</p>
<p><strong>Be kind to yourself during this stage. Becoming confident in your coding skills takes time.</strong> Nobody expects you to know everything and write code on par with senior developers. Embrace being a newbie.</p>
<h3 id="mentoring">Mentoring</h3>
<p>Having a mentor is not a requirement when becoming a developer. For most of my career-change journey, I&#39;ve managed to do things on my own. But when I briefly tried mentorship during React Nights, I definitely saw the benefits; it helps you get clarity on many things. From the coding logic you use to technologies you should be learning as a developer, mentorship provides a lot of answers and puts them at your fingertips.</p>
<p>There are specialized websites you can Google to find a mentor. Some are free, some are paid. Or you can take things into your own hands and ask someone to mentor you, be it in person or via Twitter or a different channel. <strong>You might be surprised, but most developers are more than happy to offer you their help</strong> — for them, it&#39;s an activity that lets them hone their skills and, in general, people tend to get satisfaction from giving advice. And of course, should you find a mentor, always respect and appreciate their time.</p>
<h3 id="teaching">Teaching</h3>
<p><strong>The ultimate way to solidify your knowledge is to teach someone what you know.</strong> For example, you can either help other friends who are learning development or write an article. The article can be published on your personal blog, Medium or places like freeCodeCamp. It is totally optional, yet great for your resume and a good habit that will help you gather feedback from others and build confidence.</p>
<h2 id="on-a-personal-note">ON A PERSONAL NOTE</h2>
<p>Learning coding can be frustrating at times. The biggest lessons often come from failing and fixing your mistakes, meaning you&#39;ll sometimes feel like you&#39;ve hit a wall. And when trying to make a career shift, hitting a wall can be especially demotivating. You may question whether it&#39;s even worth it. Whether it&#39;s too big of a risk. My advice is, just remember why you decided to do it in the first place. And try to make the learning process fun!</p>
<p>Having successfully made the jump, I can now say with absolute certainty — to me, this career, this lifestyle, is worth it. And making a big career change later in life than most people, that in itself is a great feeling.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Integrate Biometrics in React Native - Overview of 3 Approaches]]></title>
            <link>/posts/how-to-integrate-biometrics-in-react-native-overview-of-3-approaches</link>
            <guid>/posts/how-to-integrate-biometrics-in-react-native-overview-of-3-approaches</guid>
            <pubDate>Mon, 13 Dec 2021 08:00:00 GMT</pubDate>
            <description><![CDATA[Being a mobile application developer, sooner or later you will face a request from your client to implement biometrics authentication and will be asked how many days it could take to release. Well, if you develop applications in React Native, the answer won't always offer itself...]]></description>
            <content:encoded><![CDATA[<h1 id="how-to-integrate-biometrics-in-react-native---overview-of-3-approaches">HOW TO INTEGRATE BIOMETRICS IN REACT NATIVE - OVERVIEW OF 3 APPROACHES</h1>
<p>Being a mobile application developer, sooner or later you will face a request from your client to implement biometrics authentication and will be asked how many days it could take to release. Well, if you develop applications in React Native, the answer won&#39;t always offer itself right away because you need to find a solution that fits both Android and iOS. Therefore, some due diligence is needed first.</p>
<blockquote>
<p>&quot;Due diligence is an investigation, audit, or review performed to confirm facts or details of a matter under consideration.&quot;</p>
</blockquote>
<p>There are several criteria you have to consider. <strong>Biometrics is usually a feature utilized in security-heavy focused applications to authenticate users</strong>; for example, your bank will likely sign your account out — either immediately once you close the app or in a very short time — to protect your finances should someone get control of your device. Therefore, security will surely play an important role in your decision-making process. Hopefully, every step you take in this direction will make it harder for a potential attacker.</p>
<p><strong>Biometrics is also meant to make life easier for users</strong> so that they don&#39;t need to input their login credentials every time they need to authenticate themselves. That is why we need to look for a user-friendly solution, meaning the libraries we decide to implement should be actively maintained and offer the latest biometrics standards expected by users.</p>
<p><strong>Finally, development time is money</strong>, so if the client&#39;s budget is limited, you have to take it into consideration and offer the best value solution.</p>
<h2 id="what-are-the-options">WHAT ARE THE OPTIONS?</h2>
<p>Once you start researching potential solutions, you will realize that <strong>you face a dilemma regarding where the big part of biometrics implementation should take place</strong>. On the backend, the mobile app or actually somewhere in between?</p>
<h3 id="1-mobile-app-implementation">1. MOBILE APP IMPLEMENTATION</h3>
<p>This approach is a very pragmatic and fast solution especially in cases <strong>when one does not want to rely on your backend counterpart&#39;s implementation</strong>. There can be many reasons: a limited client&#39;s budget, time sensitivity when the backend team is focused on another feature or just no need for a complex solution.</p>
<p>How does it work? Upon the user&#39;s first signup or login, we can <strong>store the user&#39;s credentials securely on the mobile device</strong> (iOS Keychain or Android Keystore). To achieve this, we can utilize, for example, the <a href="https://github.com/oblador/react-native-keychain">react-native-keychain</a> library that allows us to hide the sensitive data behind biometrics authentication. Once a user&#39;s authenticated session expires, we offer a biometrics challenge and, if successfully passed, we retrieve the stored credentials to initiate a login API call.</p>
<p><img src="/images/mobileBiometricsFlow.jpg" alt="Mobile biometrics flow"></p>
<p>This solution is not very sophisticated and therefore has some drawbacks. For example, if the mobile application complements a website where the user can <strong>change or reset his/her password</strong>, the next mobile login request after biometrics authentication will fail and we will need to ask for the user&#39;s credentials again.</p>
<p><strong>Security might also be quite a concern</strong> because the user&#39;s credentials are stored on a mobile device, which is not considered best practice. The <a href="https://github.com/oblador/react-native-keychain">react-native-keychain library warns</a> that the data could even be easily decrypted on devices running older than the Android 6.0 operating system. <strong>Use this option for fast implementation and simple flows where security is not the highest priority</strong>.</p>
<h3 id="2-backend-implementation">2. BACKEND IMPLEMENTATION</h3>
<p><strong>Having backend implementation allows us to utilize an extra layer of security</strong>, which is desirable for applications that want to go the extra mile in securing users&#39; data.</p>
<p>The solution that offers itself is utilizing <strong>an RSA algorithm by creating a public/private key pair</strong> on the device when biometric authentication gets enabled. One way is to keep the private key securely on the device while the public key travels to the backend and is saved under the particular user. Note that one user can have multiple devices, meaning multiple public keys.</p>
<p><img src="/images/rsa.jpg" alt="RSA flow"></p>
<p>Source: <a href="https://android-developers.googleblog.com/2015/10/new-in-android-samples-authenticating.html">android-developers.googleblog.com</a></p>
<p>As the diagram shows, upon biometric authentication (step 3) the private key signs a piece of data, sends it to the backend (4) and then the backend uses the paired public key to verify the data and sends back the result (5). In case of a login action, it will return an access token to initiate a new session. Alternatively, we could generate key pairs on the backend and make the mobile app request the public key. <strong>Remember that the private key should not travel</strong>.</p>
<p>This way, we shift a big portion of work to the backend, <strong>which can lead to much longer delivery time and cost for the client</strong>. On the other hand, <strong>this approach can be reused</strong> in other parts of the application, like approving financial transactions with biometrics — unlike in the first option, where credentials can only be used for a single purpose.</p>
<p>In React Native, this solution is readily available with the <a href="https://github.com/SelfLender/react-native-biometrics">react-native-biometrics</a> library, which is, unfortunately, not actively maintained (last commit 2/2020) and its biometrics part does not support the latest standards, such as fallback to passcode when Face ID fails.</p>
<p><strong>To offer the users the best experience, we can implement our approach with two separate libraries:</strong> <a href="https://docs.expo.dev/versions/latest/sdk/local-authentication/">expo-local-authentication</a> for the biometrics part and <a href="https://www.npmjs.com/package/react-native-rsa-native">react-native-rsa-native</a> for the RSA algorithm. <strong>Use this option for a more security-focused approach when backend resources are available and the deadline is not a week.</strong></p>
<h3 id="3-combined-implementation">3. COMBINED IMPLEMENTATION</h3>
<p>If our application utilizes refresh tokens, we can smartly combine the two previous options together. Upon signup or login, <strong>we can store a new refresh token securely on the device</strong> using the <a href="https://github.com/oblador/react-native-keychain">react-native-keychain</a> library mentioned in the mobile app implementation. Once our session expires, we prompt the user to retrieve the refresh token stored behind biometrics authentication. If the user passes the challenge, we use the refresh token to call the backend and refresh the session/get a new access token.</p>
<p>The big security advantage compared to the first solution is that <strong>we don&#39;t have to keep the sensitive login credentials stored on the device</strong>. Also, backend verification of the refresh token provides certain security aspects we implemented with the second solution.</p>
<p>Overall, this approach is very practical to implement, especially in the case when refresh tokens are already utilized. The only downside is that it has a single purpose of refreshing the user&#39;s session.</p>
<h2 id="summary">Summary</h2>
<p>While implementing biometric authentication on React Native is definitely not rocket science, time needs to be invested into due diligence to find the best solution that balances important criteria such as security, cost-effectiveness and user experience.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Integrate Plaid SDK to React Native Using Expo Config Plugins]]></title>
            <link>/posts/how-to-integrate-plaid-sdk-to-react-native-using-expo-config-plugins</link>
            <guid>/posts/how-to-integrate-plaid-sdk-to-react-native-using-expo-config-plugins</guid>
            <pubDate>Mon, 27 Dec 2021 08:00:00 GMT</pubDate>
            <description><![CDATA[Previously, if you wanted to integrate Plaid React Native SDK to Expo, you either had to forcefully eject to bare workflow or use a webview solution which could result in some funny unexpected issues.]]></description>
            <content:encoded><![CDATA[<h1 id="how-to-integrate-plaid-sdk-to-react-native-using-expo-config-plugins">HOW TO INTEGRATE PLAID SDK TO REACT NATIVE USING EXPO CONFIG PLUGINS</h1>
<p>Previously, if you wanted to integrate <a href="https://github.com/plaid/react-native-plaid-link-sdk">Plaid React Native SDK</a> to Expo, you either had to forcefully eject to bare workflow or use a <a href="https://github.com/burstware/expo-plaid-link">webview solution</a> which could result in some funny unexpected issues such as <a href="https://github.com/burstware/expo-plaid-link/issues/15">this recaptcha pop up</a>.</p>
<p>Well, in case you have stumbled upon my previous guide to <a href="/posts/a-step-by-step-guide-to-writing-your-first-expo-config-plugin">Expo config plugins</a>, you already know that customizing Expo managed workflow is more than possible and therefore, in this tutorial, we will look at a bit more advanced example how to integrate <a href="https://plaid.com/">Plaid</a>, a reliable service to connect financial accounts to our app.</p>
<h2 id="setup">SETUP</h2>
<p>To get started you can use <a href="https://github.com/AronBe/article-expo-plaid-config-plugin">this Github repository</a> as a starter or just follow these commands:</p>
<p>Initiate a new Expo project - here with typescript for better DX:</p>
<pre><code class="language-sh">expo init expo-plaid-sdk-integration  -t expo-template-blank-typescript
</code></pre>
<p>Add the React Native Plaid SDK library:</p>
<pre><code class="language-sh">yarn add react-native-plaid-link-sdk
</code></pre>
<p>Update <code>App.tsx</code> to:</p>
<pre><code class="language-tsx">import React from &#39;react&#39;
import { StyleSheet, Text, View } from &#39;react-native&#39;
import { PlaidLink, LinkSuccess, LinkExit } from &#39;react-native-plaid-link-sdk&#39;

export default function App() {
  return (
    &lt;View style={styles.container}&gt;
      &lt;PlaidLink
        tokenConfig={{ token: &#39;#GENERATED_LINK_TOKEN#&#39;, noLoadingState: false }}
        onSuccess={(success: LinkSuccess) =&gt; console.log(success)}
        onExit={(exit: LinkExit) =&gt; console.log(exit)}
      &gt;
        &lt;Text&gt;Add Account&lt;/Text&gt;
      &lt;/PlaidLink&gt;
    &lt;/View&gt;
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: &#39;#fff&#39;,
    alignItems: &#39;center&#39;,
    justifyContent: &#39;center&#39;
  }
})
</code></pre>
<p>And include iOS bundleIdentifier and Android package name of your choice to <code>app.json</code>:</p>
<pre><code class="language-json">&quot;expo&quot;: {
    ...otherProps,
    &quot;ios&quot;: {
        &quot;supportsTablet&quot;: true,
        &quot;bundleIdentifier&quot;: &quot;com.expo.plaid&quot;
    },
    &quot;android&quot;: {
        &quot;adaptiveIcon&quot;: {
            &quot;foregroundImage&quot;: &quot;./assets/adaptive-icon.png&quot;,
            &quot;backgroundColor&quot;: &quot;#FFFFFF&quot;
      },
      &quot;package&quot;: &quot;com.expo.plaid&quot;
    }
}
</code></pre>
<p>If you now try running the application through Expo Go, you will likely see this error...</p>
<blockquote>
<p>TypeError: null is not an object (evaluating &#39;_reactNative.NativeModules.RNLinksdk.continueFromRedirectUriString&#39;)</p>
</blockquote>
<p>...which should be expected.</p>
<h2 id="plaid-integration">PLAID INTEGRATION</h2>
<p>To start integrating Plaid we will need to run the app through <a href="https://docs.expo.dev/development/getting-started/">expo-dev-client</a> which we can achieve either by using <code>expo run</code> <a href="https://blog.expo.dev/introducing-expo-run-commands-835ae8da4813">commands</a> locally or using EAS build process. By building the dev client we will have a custom Expo Go which will add the Plaid library to its bundle, meaning you can use this client until you decide to add again something new that is not supported by it. For simplicity we will stay with the local <code>run</code> commands. Then we just need to follow the Plaid <a href="https://github.com/plaid/react-native-plaid-link-sdk">readme</a> setup guide for both iOS and Android.</p>
<h3 id="ios-setup">iOS setup</h3>
<p>This is actually super simple. The readme suggests adding to <code>ios/Podfile</code> following string <code>pod &#39;Plaid&#39;, &#39;~&gt; &lt;insert latest version&gt;</code> to pin the latest version, but, in reality, this is optional and we can easily work with the version currently bundled in the library. As a result, the only step we have to do is to initiate the <code>expo-dev-client</code> by running:</p>
<pre><code class="language-sh">expo run:ios
</code></pre>
<p>After the build process finishes, the app launches without the error we experienced previously. You can press <code>Add Account</code> and you should see Plaid error complaining about the token we provided - but about that later.</p>
<blockquote>
<p>Unexpected environment string value: (null). Expected one of: production, sandbox, or
development.</p>
</blockquote>
<h3 id="android-setup">Android setup</h3>
<p>If you run <code>expo run:android</code> and press <code>Add Account</code> at this stage, you will get an unhandled promise rejection..</p>
<blockquote>
<p>TypeError: null is not an object (evaluating &#39;_reactNative.NativeModules.PlaidAndroid.startLinkActivityForResult&#39;)</p>
</blockquote>
<p>..because there are actually bunch of steps to make Android work and as the <a href="https://github.com/plaid/react-native-plaid-link-sdk#android-setup">readme</a> suggests it is due to TurboModules not supporting autolinking. But in general this is nothing we cannot setup ourselves with Expo config plugins.</p>
<h4 id="1-setup-your-app-id">1) Setup your app id</h4>
<p>This change you have to do on Plaid Dashboard at the <code>API</code> <a href="https://dashboard.plaid.com/team/api">page</a> - <code>Allowed Android Package</code>. You should configure there the Android package name from <code>app.json</code> - <code>com.expo.plaid</code>.</p>
<h4 id="2-update-mainapplicationjava">2) Update MainApplication.java</h4>
<p>Here we have to fullfil 2 requirements:</p>
<ul>
<li><code>Add import com.plaid.PlaidPackage; to the imports section</code></li>
<li><code>Add packages.add(new PlaidPackage()); to List&lt;ReactPackage&gt; getPackages();</code></li>
</ul>
<p>Which we can do only with an <strong>expo config plugin</strong>:</p>
<p>Create in the root of your project <code>withAndroidPlaid.ts</code> file and start transpiling it to javascript with this command:</p>
<pre><code class="language-sh">yarn tsc withAndroidPlaid.ts --watch --skipLibCheck
</code></pre>
<p>and import it in <code>app.json</code> as a plugin:</p>
<pre><code class="language-json">{
  &quot;expo&quot;: {
    ...otherProps,
    &quot;plugins&quot;: [&quot;./withAndroidPlaid&quot;]
  }
}
</code></pre>
<p>Finally, change <code>withAndroidPlaid.ts</code> content to following:</p>
<pre><code class="language-ts">import type { ConfigPlugin } from &#39;@expo/config-plugins&#39;
import { withMainApplication } from &#39;@expo/config-plugins&#39;

function applyPackage(mainApplication: string) {
  const plaidPackageImport = `import com.plaid.PlaidPackage;\n`
  const plaidAddPackage = `packages.add(new PlaidPackage());`

  // Make sure the project does not have the settings already
  if (!mainApplication.includes(plaidPackageImport)) {
    mainApplication = mainApplication.replace(
      /package com.expo.plaid;/,
      `package com.expo.plaid;\n${plaidPackageImport}`
    )
  }

  if (!mainApplication.includes(plaidAddPackage)) {
    mainApplication = mainApplication.replace(
      /return packages;/,
      `
    ${plaidAddPackage}
    return packages;
    `
    )
  }

  return mainApplication
}

const withAndroidPlaid: ConfigPlugin = (expoConfig) =&gt; {
  expoConfig = withMainApplication(expoConfig, (config) =&gt; {
    config.modResults.contents = applyPackage(config.modResults.contents)
    return config
  })

  return expoConfig
}

export default withAndroidPlaid
</code></pre>
<p>If you look closely, our plugin is utilizing <code>withMainApplication</code>, a <a href="https://docs.expo.dev/guides/config-plugins/#mod-plugins">mod</a> provided by Expo allowing us to read and modify the content of <code>MainApplication.java</code>. We provide the content to our function <code>applyPackage</code> where we execute 2 string replacements to insert <code>plaidPackageImport</code> and <code>plaidAddPackage</code> constants into the file - the changes Plaid readme wanted from us.</p>
<blockquote>
<p>Our strategy is to simply find a stable part of the file where we can append our changes. Due to the string replacement nature, <strong>it is quite dangerous thing to rely on, because they could change with consequent React Native and Expo updates</strong> - so be sure these replacements still work when you upgrade.</p>
</blockquote>
<p>If you run <code>expo prebuild -p android</code> you should now see updated <code>MainApplication.java</code>. If you did something incorrectly, you may want to discard changes, check your plugin code, and try <code>prebuild</code> again.</p>
<h4 id="3-update-appbuildgradle">3) Update app/build.gradle</h4>
<p>We need to update dependencies to following:</p>
<pre><code class="language-java">dependencies {
    // ...
    implementation project(&#39;:react-native-plaid-link-sdk&#39;)
}
</code></pre>
<p>Which we can do utilizing <code>withAppBuildGradle</code> modifying the file within <code>withAndroidPlaid</code> function.</p>
<pre><code class="language-ts">// ...
expoConfig = withAppBuildGradle(expoConfig, (config) =&gt; {
  config.modResults.contents = applyImplementation(config.modResults.contents)
  return config
})
// ...
</code></pre>
<p>And <code>applyImplementation</code> is our custom function following the previous strategy of appending <code>plaidImplementation</code> string to the right place of the file.</p>
<pre><code class="language-ts">function applyImplementation(appBuildGradle: string) {
  const plaidImplementation = `implementation project(&#39;:react-native-plaid-link-sdk&#39;)`

  // Make sure the project does not have the dependency already
  if (!appBuildGradle.includes(plaidImplementation)) {
    return appBuildGradle.replace(
      /dependencies\s?{/,
      `dependencies {
    ${plaidImplementation}`
    )
  }

  return appBuildGradle
}
</code></pre>
<h4 id="4-update-settingsgradle">4) Update settings.gradle</h4>
<p>Finally, we have to append following string to <code>settings.gradle</code>:</p>
<pre><code class="language-java">include &#39;:react-native-plaid-link-sdk&#39;
project(&#39;:react-native-plaid-link-sdk&#39;).projectDir = new File(rootProject.projectDir, &#39;../node_modules/react-native-plaid-link-sdk/android&#39;)
</code></pre>
<p>Which can be done using <code>withSettingsGradle</code> Expo mod:</p>
<pre><code class="language-ts">expoConfig = withSettingsGradle(expoConfig, (config) =&gt; {
  config.modResults.contents = applySettings(config.modResults.contents)
  return config
})
</code></pre>
<p>And making the changes with our custom <code>applySettings</code> function. Notice that we are just concatenating the strings with <code>plus</code> symbol given that we don&#39;t really care about the exact placement of <code>plaidSettings</code> constant.</p>
<pre><code class="language-ts">function applySettings(gradleSettings: string) {
  const plaidSettings = `include &#39;:react-native-plaid-link-sdk&#39;
  project(&#39;:react-native-plaid-link-sdk&#39;).projectDir = new File(rootProject.projectDir, &#39;../node_modules/react-native-plaid-link-sdk/android&#39;)`

  // Make sure the project does not have the settings already
  if (!gradleSettings.includes(`include &#39;:react-native-plaid-link-sdk&#39;`)) {
    return gradleSettings + plaidSettings
  }

  return gradleSettings
}
</code></pre>
<blockquote>
<p>If you lost track of the changes or applied them incorrectly, you can always go to the solution branch of <a href="https://github.com/AronBe/article-expo-plaid-config-plugin/tree/solution">this github repository</a> for my final implementation.</p>
</blockquote>
<blockquote>
<p><strong>Troubleshooting</strong>: I have discovered 2 potential issues when implementing Plaid on Android, so if you are facing build errors or your app is crashing, you might find an answer in these github issues: <a href="https://github.com/plaid/react-native-plaid-link-sdk/issues/392#issuecomment-868857758">Kotlin version</a> and <a href="https://github.com/plaid/react-native-plaid-link-sdk/issues/146#issuecomment-648286809">OkHttp version</a>.</p>
</blockquote>
<p>After applying all necessary changes you should just run <code>expo run:android</code> to build the app with all modifications.</p>
<p>Once the build process finishes and the app launches, you can press <code>Add Account</code> and you should see a different Plaid error complaining about configuration - but it is actually about the fake token we have provided.</p>
<blockquote>
<p>null - unable to open link, please check that your configuration is valid</p>
</blockquote>
<h3 id="getting-the-link-token">Getting the link token</h3>
<p>At this point, you just need to provide a correct link token in <code>App.tsx</code>. Normally you would get it from your backend, but for testing purposes we can actually use a very handy <a href="https://github.com/plaid/plaid-postman">Postman collection</a> provided by Plaid.</p>
<p>After going through the setup and utilizing your <code>client_id</code> and <code>secret</code> from Plaid dashboard, you can hit <code>https://sandbox.plaid.com/link/token/create</code> API endpoint and use the returned <code>link_token</code>.</p>
<pre><code class="language-json">{
  &quot;expiration&quot;: &quot;2021-12-25T19:49:22Z&quot;,
  &quot;link_token&quot;: &quot;link-sandbox-965dbc89-14fc-4122-b900-27a562de6db0&quot;,
  &quot;request_id&quot;: &quot;AEBgG6EbWGsQ9aR&quot;
}
</code></pre>
<p>Now pressing <code>Add Account</code> should finally open Plaid interface:</p>
<p><img src="/images/plaid.png" alt="Plaid interface"></p>
<h2 id="summary">Summary</h2>
<p>This integration might feel scary at first, but in the end we are just doing the same thing over and over - inserting a string into a native file during the build time (or prebuild time more specifically). Note that the Expo mods we used are marked as dangerous given that they rely on our custom string replacement rules and you should expect them to break in the future. But for now, they are the best way how to combine the Expo managed workflow and
Plaid React Native SDK.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[(Portfolio Update) Ascension - Reaching the number 1 Bible app spot in the US App Store]]></title>
            <link>/posts/portfolio-update-ascension</link>
            <guid>/posts/portfolio-update-ascension</guid>
            <pubDate>Sun, 06 Aug 2023 20:00:00 GMT</pubDate>
            <description><![CDATA[When I was asked to lead Ascension mobile development, leaving The Pump, Arnold Schwarzenegger's official fitness app, felt bit sad, because it seemed like nothing bigger can come after that. Well, I couldn't be more wrong. Releasing Ascension was my biggest success story as a developer, with the application gaining the number 1 spot in the US App Store reference category.]]></description>
            <content:encoded><![CDATA[<p>import { Callout } from &#39;nextra/components&#39;
import Image from &#39;next/image&#39;</p>
<p>When I was asked to lead Ascension mobile development, leaving <a href="/posts/portfolio-update-the-pump">The Pump</a>, Arnold Schwarzenegger&#39;s official fitness app, felt bit sad, because it seemed like nothing bigger can come after that. Well, I couldn&#39;t be more wrong. <strong>Releasing Ascension was my biggest success story as a developer</strong>, with the application gaining <strong>the number 1 spot in the US App Store reference category</strong>, reaching the <strong>36th place in the broad US App Store free apps category</strong>, gaining over <strong>50,000 registered users within a first 24 hours</strong>, and finally keeping <strong>rating 4.9+</strong> ⭐️ on both iOS and Android platforms.</p>
<p><img src="/images/ascension_reference.png" alt="US Reference Chart"></p>
<h2 id="ascension">Ascension</h2>
<p>The client, <a href="https://ascensionpress.com/">Ascension Press</a>, is a publisher of Catholic books and digital media, and they have <strong>huge amount of digital content</strong>, with podcasts The Bible in a Year and The Catechism in a Year, probably being the most popular, especially among the US audience. <strong>So popular that The Catechism in a Year was just behind the Joe Rogan Experience in the USA top podcasts</strong>. Therefore, the client tasked STRV in building a mobile application to <strong>unite all their digital content</strong> with the Bible and the Catechism (2 books + 2 podcasts) being the centerpiece of everything.</p>
<p><Image
  src="/images/ascension_podcast.jpg"
  width={300}
  height={300}
  alt="Ascension Free Chart"
/></p>
<p>As you can imagine, this was quite a technical challenge, yet we kept the team reasonably sized with 2 core frontend engineers and 1 core backend engineer to keep the efficiency high. To hit our milestones safely, we would eventually bring +1 for both FE and BE. And as usual, we were accompanied by 1 PM, 1 QA (+1 before the launch), and 1 designer. The application didn&#39;t require any strong native integration, therefore <strong>React Native</strong> was picked to provide the client with <strong>fast and efficient development</strong>.</p>
<p><Image
  src="/images/ascension_app.jpeg"
  width={300}
  height={300}
  alt="Ascension App"
/></p>
<h2 id="development">Development</h2>
<p>Before we could even start developing, we had to figure out the <strong>biggest technical challenge - how to display the Bible and the Catechism</strong>. We knew we needed <strong>interactions</strong> such as highlights, taking notes, text resizing, saving last position, cross referencing to certain book sections, which is something eBooks have figured out before us, therefore a Webview implementation with <a href="https://github.com/futurepress/epub.js">epub.js</a> was considered. But we also needed <strong>custom design</strong> and ability to <strong>dynamically insert certain additional content</strong> before or after specific verses/paragraphs to provide even more depth to the original books.</p>
<p>We understood we need an absolute control for the best user experience, so we undertook an epic quest of <strong>creating our custom data structure and parsing ePub version of the books</strong> with its enormous content into it. And given the &quot;static&quot; nature of the books (in other words, the Bible won&#39;t change), it was actually a safe decision <strong>allowing storing indexed interactions on the backend</strong>, but keeping the <strong>content on the frontend</strong> and making the books and search for the users <strong>offline</strong> as default.</p>
<p>Nevertheless, it turned out that there were many <strong>more technical challenges</strong> we had to face after that and <strong>push React Native to its limits</strong>.</p>
<p>One of them were <strong>long lists</strong> of content, React Native&#39;s main nemesis. While the Bible chapters are relatively well sized, the Catechism chapters can have <strong>over 200 paragraphs</strong>. Moreover, we could not display simple text, because the parsed content actually had to include <strong>html</strong> tags to apply to certain words italics or bold styles, and also to keep <code>&lt;a&gt;</code> tags to custom render footnotes and references to other book sections. The amazing library <a href="https://github.com/meliorence/react-native-render-html">react-native-render-html</a> helped us tremendously with rendering, but the performance suffered quite a bit. It could have been easily solved by using recycling from <a href="https://shopify.github.io/flash-list/">Flashlist</a>, but <strong>Flashlist is unable to scroll precisely to a specific index when content is not consistently sized</strong>, which was a crucial user experience interaction to access the exact last location or navigate to a specific highlight or reference. So we got stuck with <code>Flatlist</code>, which by the way is not great in it either, but is able to make it work when you set <code>initialNumToRender</code> to your desired index, but you can imagine what happens to the JS thread when you set it to 200. Eventually, we made Catechism content more granular, splitting chapters into articles and smartly optimizing our components with <code>memo</code>, which mostly resolved our performance issue. Finally, on top of it we added a skeleton loader to make the user experience even better.</p>
<Callout type="info" emoji="👨‍💻">
  I actually found a way how to make the scroll with Flashlist work, but it
  requires to scroll to the given index at least 3 times within 1000ms using
  timeouts, so that Flashlist has time to correct its calculation of the
  location. From user experience point of view, this can work only if you cover
  the reader screen with a loader/skeleton, do your index scrolling, and then
  show the user the reader and hope it worked 😅. Currently, there was not
  enough time and faith for the refactor, but it is on my mind.
</Callout>

<p>Basically, the application already replicates a fully fledged <strong>eBook reader</strong> functionality, with some cool features such as scroll up/down to go to previous/next chapters/locations, but again there was much more to build. For example, a <strong>fully fledged podcast player</strong> with <strong>transcripts</strong> and a <strong>global miniplayer</strong> allowing you to navigate the rest of the app while listening.</p>
<p>As big believers in Expo, we started with <a href="https://docs.expo.dev/versions/latest/sdk/av/">Expo AV</a>, but we quickly realized we would be missing out on <strong>iOS lock screen audio controls</strong> and promptly switched to more feature rich <a href="https://github.com/doublesymmetry/react-native-track-player">react-native-track-player</a>. The library is currently in v4 release candidate status, but it is already stable. The library helps nicely with <strong>queueing</strong> of audio tracks, <strong>progress tracking</strong> and each track can carry extra <strong>metadata</strong> to access anywhere in the app. At the time of writing, the Ascension app has <strong>4 various audio types</strong> (the two podcasts, individual Bible Answers tracks, the Bible as an audio book, Bible Studies playlists), so metadata helped tremendously to separate progress tracking/queuing logic for each one of them. Finally the library&#39;s documentation is clear and helped us to easily implement an <strong>offline listening</strong> feature, which all users wanted the most.</p>
<p>As a part of the Bible Answers (<strong>1000 pieces</strong> of inserted content to certain parts of the Bible - text, images, audio, video), we also implemented a <strong>video player</strong> using both <a href="https://github.com/react-native-video/react-native-video">react-native-video</a> and Expo av. We found that on iOS we couldn&#39;t use Expo AV for video, because it was overriding native settings of the audio player and lock screen audio controls would be lost again. Therefore, we switched to react-native-video, but found issues on Android with full screen controls and orientation. That is why we ended up with react-native-video on iOS and Expo AV for videos on Android. React Native at its best 😅. But lets be honest, it is so great to have the option to split the logic based on a platform.</p>
<p>This is already my longest portfolio article, but there is still so many more things to talk about. For example, after two previous GraphQL projects, our backend engineers chose a REST api, therefore <a href="https://tanstack.com/query/latest/">React Query</a> was chosen to help with the API management. Given, that with GraphQL you can easily generate types and React Query hooks from a schema, I was searching for a way how to do it with REST. I remembered when I was playing with Supabase 2 years back (<a href="https://www.youtube.com/watch?v=1BOYWzbHpH0">public talk</a>), the had types generation thanks to <a href="https://www.openapis.org/">OpenAPI</a>, therefore I persuaded our amazing backend engineer to <strong>maintain an OpenAPI schema</strong> and used <a href="https://github.com/fabien0102/openapi-codegen">this OpenAPI codegen</a> to generate types and React Query hooks to make the project more <strong>maintainable</strong>. Eventually, I also migrated the project to a <strong>monorepo</strong>, so that we could reuse the api and other things on the admin.</p>
<p>Finally, I am just at the bring of launching subscriptions to give users access to even more premium digital content. <a href="https://www.revenuecat.com/">Revenue Cat</a> has proven to be a great choice for <a href="/posts/portfolio-update-the-pump">The Pump</a>, therefore I picked it for Ascension as well.</p>
<h2 id="summary">Summary</h2>
<p>At the time of writing, the Ascension project is still ongoing and there is still <strong>so much more content to incorporate into the app</strong>. Besides new features, Ascension constantly monitors <strong>feedback</strong> (among other smart things their amazing team does) from <strong>the users, who are generally bit older</strong>, so they bring valuable insights, how to <strong>make the app easy to use for everyone</strong>.</p>
<p>Over 6 weeks since the launch (<strong>28 June, 2023</strong>), we have already gathered over <strong>10,000 ratings on iOS and 2,600 on Android</strong>, still keeping the rating <strong>4.9+</strong> ⭐️ on both platforms.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[(Portfolio Update) Bitcoin IRA - Investing in cryptocurrencies using your retirement account]]></title>
            <link>/posts/portfolio-update-bitcoin-ira</link>
            <guid>/posts/portfolio-update-bitcoin-ira</guid>
            <pubDate>Sun, 06 Aug 2023 16:00:00 GMT</pubDate>
            <description><![CDATA[When I transitioned from my Financial Markets career to Frontend development, I expected to leave the world of finance behind. Yet, as it turned out, I could not escape that easily 🤔. My first three projects at STRV were all related to finance by pure coincidence. Besides Rich Uncles (a REIT investment platform, renamed to Modiv) and Stride Health (an insurance platform), I also worked on Bitcoin IRA, a platform that allows you to invest in cryptocurrencies using your retirement account.]]></description>
            <content:encoded><![CDATA[<p>import Image from &#39;next/image&#39;</p>
<p>When I transitioned from my <a href="/posts/how-i-left-a-financial-markets-career-for-web-development">Financial Markets career to Frontend development</a>, I expected to leave the world of finance behind. Yet, as it turned out, I could not escape that easily 🤔. My first three projects at STRV were all related to finance by pure coincidence. Besides <a href="https://www.modiv.com/">Rich Uncles</a> (a REIT investment platform, renamed to Modiv) and <a href="https://www.stridehealth.com/">Stride Health</a> (an insurance platform), I also worked on <a href="https://bitcoinira.com/">Bitcoin IRA</a>, a platform that allows you to invest in cryptocurrencies using your retirement account.</p>
<p><img src="/images/bitcoin_ira.webp" alt="Bitcoin IRA"></p>
<p>Obviously, for each developer it is very helpful to understand the context of the client&#39;s business, because while developing new features you are able to <strong>predict possible edge cases and actually shift the client to the right direction</strong> by understanding both the business logic and possible hurdles in development. So all in all, it was a good way how to start my career at STRV.</p>
<h2 id="bitcoin-ira">Bitcoin IRA</h2>
<p>At the time (<strong>August 2020</strong>), Bitcoin IRA already had a working web application in React, so it made sense to expand the offering for a mobile solution using <strong>React Native</strong>, allowing client&#39;s engineers to eventually pick up React Native and maintain both applications. At STRV, our team consisted of two React Native engineers, one PM, one QA and one designer, with backend provided by the client. Especially having own STRV designer is always a big win resulting in faster development thanks to a consistent design system and well structured Figma files. You can see the simple and clean designs in the <strong>official STRV case study</strong> <a href="https://www.strv.com/our-work/bitcoin-ira">here</a>.</p>
<h2 id="development">Development</h2>
<p>This was officially my first React Native project, therefore, as it used to be during my financial career, I just surrounded myself with various information sources to consume lots of React Native knowledge quickly (Youtube, Twitter, podcasts, Reddit, Github repos) and apply it to the project. Eventually after 3-4 months of development, my senior colleague moved to a different project and <strong>I was left to finish the project on my own</strong>. This was a great experience and source of many lessons I documented in my <a href="/posts/what-i-learned-as-a-web-dev-on-my-first-react-native-project">article about the transition from React to React Native</a>. The biggest lesson was obviously <strong>successfully launching the application to production</strong>, which not every juniorish React Native developer gets to experience that early and learn all the ins and outs of Google and Apple store release management. Thanks to that I got rid of my remaining imposter syndrome and I was able to move on to more challenging projects.</p>
<p>Regarding the tech stack tidbits, it included <strong>Redux Toolkit</strong> combined with <strong>Redux Sagas</strong> for a better control of API requests and data flows, which is crucial for each financial application. Unfortunately, <strong>React Query</strong> was just becoming a thing and it was too risky to bet on it and as a newcomer to React Native I didn&#39;t have enough leverage to push for it. From a hindsight, it would make the development much easier and more maintainable. Especially polling for updated asset prices during a trading flow would be a piece of cake with React Query.</p>
<p>Similarly, forms are crucial for financial apps and <strong>Formik</strong> &amp; <strong>Yup</strong> were the best to offer for form handling and validation at the time, but these projects became quite hard to maintain for the community with Github issues piling up, therefore I eventually refactored everything to more agile <strong>React Hook Form</strong> &amp; <strong>Zod</strong>, which both have became my go-to and battle tested forms solution.</p>
<p>Finally, to boost security and improve user experience, among other measures, <strong>biometric authentication</strong> was implemented, which eventually made me to document it and share lessons in <a href="https://www.youtube.com/watch?v=HOujkEr2Ta8">one my first public talks</a>.</p>
<h2 id="summary">Summary</h2>
<p>Checking the <strong>4.5</strong>⭐️ <strong>rating</strong> on both AppStore and Play Store, I am very happy with the outcome of my first React Native project. Staying eventually alone on the project was a crucial test for myself and I am glad I was able to eventually release the project to the client&#39;s satisfaction. Also this was an era <strong>before Expo and EAS became our go-to at STRV</strong>, therefore I had an opportunity to <strong>get hands dirty</strong> with native code changes, React Native upgrades and certificates management - <strong>a valuable lesson some developers might not get to experience with Expo these days</strong>.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[(Portfolio Update) Nutiliti - Utility bills sharing and more]]></title>
            <link>/posts/portfolio-update-nutiliti</link>
            <guid>/posts/portfolio-update-nutiliti</guid>
            <pubDate>Sun, 06 Aug 2023 18:00:00 GMT</pubDate>
            <description><![CDATA[At the time (September 2021), Nutiliti had already launched their React Native application to the App Store, but it was bit rushed to capture the upcoming new school year tenancy changes. Therefore, at STRV we were tasked to bring the application to a more stable state, launch the Android version, extend the payment options to include bank accounts and more.]]></description>
            <content:encoded><![CDATA[<p>import Image from &#39;next/image&#39;</p>
<p>After <a href="/posts/portfolio-update-bitcoin-ira">three financial projects</a> in a row, I was sure something new is around the corner. Almost correct 🙂.</p>
<h2 id="nutiliti">Nutiliti</h2>
<p><a href="https://www.nutiliti.com/">Nutiliti</a> started as an application <strong>allowing flatmates to split utility bills</strong> (by percentage or a fixed amount) by simply connecting their credit cards and Nutiliti would handle the rest - basically charging everyone its bill portion. Over 6 years studying and working in the UK, I had 19 different flatmates (London to blame 🤦‍♂️, people just come and go), so I could see it working by removing the hassle to chase everyone to pay their part.</p>
<p>At the time (<strong>September 2021</strong>), <strong>Nutiliti</strong> had already launched their React Native application to the AppStore, but it was bit rushed to capture the upcoming new school year tenancy changes. Therefore, at STRV we were tasked to <strong>bring the application to a more stable state, launch the Android version, extend the payment options to include bank accounts and more.</strong></p>
<Image src="/images/nutiliti.png" width={300} height={600} alt="Nutiliti app" />
## Development

<p>The client gave me full autonomy to work on the React Native application, so I jumped into the codebase, added <a href="https://github.com/strvcom/code-quality-tools">STRV code quality tools</a> (ESLint, Prettier, Husky, lint-staged) and started the <strong>refactor</strong>. Luckily the code base was already mostly in typescript, so it went quite fast.</p>
<p>Because the backend was in <strong>GraphQL</strong>, as the next logical step I implemented <strong>automatic code generation</strong> for types and Apollo Client queries and mutations hooks. All this made the codebase much more <strong>maintainable</strong> and easier to work with.</p>
<p>The application consisted of a lengthy onboarding flow to gather all the necessary tenancy information, so this was a great candidate for <strong>E2E testing implementation</strong>. At the time, <a href="https://wix.github.io/Detox/">Detox</a> was the best choice for the task.</p>
<p>All above was possible only thanks to the client&#39;s CTO, who understood the <strong>importance of code quality and testing for long-term success</strong>, and was willing to invest into it. <a href="https://clutch.co/profile/strv">STRV</a> is one of the most expensive agencies out there (but worth every penny!), so you can imagine it is hard to persuade clients to invest into refactors and almost impossible to find clients who would actually propose it themselves.</p>
<p>It is also worth mentioning that the client started the application in <a href="https://expo.dev/">Expo</a>, a React Native framework that we avoided at STRV for a long time due to its limitations. However, I knew it was the <strong>turning period for Expo</strong>, which introduced a <strong>modern set of tools such as expo-dev-client and Expo Application Services</strong>, basically allowing to build React Native applications with any native customization you would like via Expo Config Plugins and making the build and submit processes super easy. Therefore, as a first to try at STRV, I went all in Expo and after this successful experience I have been evangelizing it to my colleagues and others ever since. Many of it is mentioned in my yearly React Native at STRV reviews (<a href="/posts/react-native-at-strv-2022">2022</a>, <a href="/posts/react-native-at-strv-2023">2023</a>).</p>
<p>Finally, as mentioned, one of the most important features was to <strong>implement bank account payments</strong>, which was a great opportunity to learn about the <a href="https://plaid.com/">Plaid</a> API, which we already used in Rich Uncles, but I was not involved in that part of the project. And because <a href="https://github.com/plaid/react-native-plaid-link-sdk">React Native Plaid SDK</a> required native changes, it was a great opportunity to implement an Expo Config Plugin and write an <a href="how-to-integrate-plaid-sdk-to-react-native-using-expo-config-plugins">article</a> about it.</p>
<h2 id="summary">Summary</h2>
<p>Working solo at Nutiliti&#39;s React Native application was a huge learning experience and especially it uncovered for us at STRV the new possibilities Expo brings to the table. <strong>Now basically all projects are built with Expo and we are loving it</strong>. Also, my Expo Config Plugin articles have become the most <strong>popular</strong> among my blog readers, because at the time besides main documentation there was literally <strong>no other source of information than my 2 articles</strong>. I am feeling bit guilty they have become bit outdated, but hopefully the approach I taught is still helpful!</p>
<p>As far as Nutiliti goes, the app has <strong>4.7</strong>⭐️ <strong>rating</strong> in the AppStore and <strong>4.0⭐️</strong> <strong>rating</strong> on Android. The app is focused on the USA and a younger target group (students, early professionals), so it is not surprising there are only 9 reviews on Android vs 98 on iOS. Also, <strong>Nutiliti has become so much more</strong> than when I left to a different project in <strong>May 2022</strong>. These days they partner with property managers and offer many new features such as energy provider switching. I wish them best of luck, because they are a great team and I am sure they will succeed!</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[(Portfolio Update) The Pump - Arnold Schwarzenegger's official fitness app]]></title>
            <link>/posts/portfolio-update-the-pump</link>
            <guid>/posts/portfolio-update-the-pump</guid>
            <pubDate>Sun, 06 Aug 2023 19:00:00 GMT</pubDate>
            <description><![CDATA[Sometimes you have to be just on the right place at the right time. Not even three years into my career as a frontend developer, together with my fullstack colleague, we were assigned to build an official mobile fitness application for Arnold Schwarzenegger himself.]]></description>
            <content:encoded><![CDATA[<p>import { Callout } from &#39;nextra/components&#39;</p>
<p>Sometimes you have to be just on the right place at the right time. Not even three years into my career as a frontend developer, together with my fullstack colleague, we were assigned to build an official mobile fitness application for <strong>Arnold Schwarzenegger</strong> himself. STRV is a top agency with presence both in San Francisco and Los Angeles, so sometimes big names come around, especially in the fitness area, which is manifested in STRV&#39;s own love for fitness and its top-floor gym.</p>
<p>Arnold’s team was looking for a first solution that could be delivered <strong>quickly</strong> (basically 3 months over Summer 2022) and altered on the go to <strong>incorporate feedback</strong> from beta testers and then later from first users. <strong>React Native’s speed of development, flexibility and cross-platform nature made it a perfect fit for the project</strong>.</p>
<h2 id="the-pump">The Pump</h2>
<p>The Pump is not only a fitness app but also a closed community of Arnold’s fans, who can interact with Arnold via discussions in motivational articles the app offers. It is for everyone, not only bodybuilders but also for total fitness beginners, with tailored workouts for each difficulty level, gender, equipment (body weight, gym) and fitness goal (get big, get shredded).</p>
<iframe
  width="100%"
  height="400"
  src="https://www.youtube.com/embed/Ir2jeynv0fs"
  title="YouTube video player"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
  allowFullScreen
></iframe>

<p>What makes it truly standout is the combination of retro and modern bold design, a true masterpiece from our designer Bara, and you can read all about it in STRV&#39;s <a href="https://www.strv.com/blog/sculpting-success-designing-a-fitness-app-for-arnold-schwarzenegger">design article</a> and also in the official <a href="https://www.strv.com/our-work/the-pump">case study</a>. As usual, our team was also accompanied by a product manager and a QA engineer.</p>
<p><img src="/images/PumpTeam.jpg" alt="The Pump Team">
<em><a href="https://www.strv.com">Our team at STRV&#39;s gym</a></em></p>
<h2 id="development">Development</h2>
<p>We knew we have to build the application fast, therefore an idea to use backend as a service was brought up. After dismissing Firebase due to potential Firestore vendor lock-in, and Supabase due to its relatively early nature not tested on a fully-fledged product by us, we decided to go with <a href="https://aws.amazon.com/amplify/">AWS Amplify</a> from Amazon. But after 2 weeks of development, we realized that our data heavy application requires a lot of custom logic, <strong>which made the implementation of Amplify more complex and slower than building a standard backend solution with full flexibility on our side</strong>. For our Node BE, besides top DX choices such as Prisma and GraphQL, we also utilized <a href="https://railway.app/">Railway</a> for the first time, and all in all, my fullstack colleague quickly caught up and replicated our Amplify data structure.</p>
<p>On the React Native side, we had lots of UI to build. Luckily, our designer was utilizing consistent spacing and typography, therefore I knew I could use a theme strict solution such as <a href="https://shopify.github.io/restyle/">Restyle from Shopify</a> to its full potential. After setting the theme and text variants up, the app was almost building itself.</p>
<p>Besides GraphQL as our data layer, on the client side I also utilized <a href="https://zustand-demo.pmnd.rs/">Zustand</a> and <a href="https://github.com/mrousavy/react-native-mmkv">MMKV</a> to persist active workout data the user would be filling in. Zustand wins over React Context with its capability and over Redux with its simplicity, and MMKV is a better alternative to AsyncStorage thanks to its synchronous nature and better performance.</p>
<Callout type="info" emoji="👨‍💻">
  It was quite a fun challenge to count total lifted weights when one workout is
  divided into sets that include exercises which can have multiple sets as well,
  with each obviously having reps and weight. Take that a fitness program is
  divided into phases and each phase is divided into individual workouts and you
  will start to realize how **complex and nested the resulting data structure
  is**.
</Callout>

<p>The Pump is a <strong>subscription-based application with a lifetime membership option</strong> as well, therefore I chose <a href="https://www.revenuecat.com/">RevenueCat</a> as our battle tested payment solution. All in all, a great experience, but once your application includes also the <strong>lifetime</strong> membership option, you have to be careful with the way you implement it. It is an <strong>in-app purchase rather than a subscription</strong>, so obviously you should make the user cancel their subscriptions first before buying a lifetime membership and also if they own one, then they should not be able to buy any subscriptions. Many things you don&#39;t have to consider when offering just subscriptions and I felt RevenueCat could do bit more to document this use case.</p>
<p>Finally worth mentioning, after successful experience on <a href="/posts/portfolio-update-nutiliti">Nutiliti</a>, starting the project with <strong>Expo</strong> was an obvious choice, proving that any native customization can be done via Expo Config Plugins and Expo Application Services are the best in class for building and submitting React Native applications.</p>
<Callout type="info" emoji="👨‍💻">
  Also part of the project was a nicely designed **landing page**
  https://thepump.app and an **admin** site. The landing page is loading pretty
  much instantly thanks to **CloudFlare Pages** and the admin was built with
  **Remix** to utilize its nested layouts capabilities (this is before Next.js
  released them as well). Looking back, hard to believe we (two engineers) built
  all of that over summer, especially when I was preparing everything for **my
  wedding in August** as well 😅.
</Callout>

<h2 id="summary">Summary</h2>
<p>After the first version of the app was finished in September 2022, as it happens in the agency development, I moved to the <a href="/posts/portfolio-update-ascension">Ascension project</a> and my fullstack colleague Michal stayed to gave the app few more final touches until the client took over the maintenance of the project. The app was eventually <strong>released in April 2023 hitting the TOP 20 in the US Health &amp; Fitness AppStore category</strong> and <strong>selling out all 5000 lifetime memberships within 72 hours</strong>. Current rating is <strong>4.4⭐️</strong> on both iOS and Android and <strong>the app is currently accessible via an invite only</strong>, most likely still in the stage to gather and incorporate feedback from its first founding users.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React Native at STRV in 2022]]></title>
            <link>/posts/react-native-at-strv-in-2022</link>
            <guid>/posts/react-native-at-strv-in-2022</guid>
            <pubDate>Fri, 25 Feb 2022 08:00:00 GMT</pubDate>
            <description><![CDATA[Looking at the applications currently under development at STRV, we have seen a major shift towards Expo, a React Native framework that tries to abstract out manipulation of native iOS and Android code to allow web engineers with knowledge of React to build mobile apps without major roadblocks.]]></description>
            <content:encoded><![CDATA[<p>For those that need an introduction, React Native is a cross-platform framework developed by Facebook that allows us to build applications for not only iOS and Android, but also Windows, macOS and web applications. The beauty of cross-platform development is that these apps can be built from a <strong>single codebase,</strong> which offers our clients several benefits.</p>
<p><img src="/images/AronSTRV-min.jpg" alt="Aron in STRV offices"></p>
<p><em><a href="https://www.strv.com">At STRV offices</a></em></p>
<p><strong>Cost-saving is usually the most apparent benefit</strong>, given that — on a typical project — a single engineer is able to work on an iOS and Android app simultaneously. The same goes for <strong>an application’s post-launch maintenance and new feature development</strong>; at this point, the client normally needs to find two native engineers to get familiar with the codebase and start working on the project. In the case of cross-platform development, the client only needs one.</p>
<p>Nevertheless, due to high demand, finding a really good React Native engineer is definitely not an easy task these days. <strong>Therefore, the math is not that simple, and 1 does not always equal 2.</strong></p>
<p><quote class="equation">1 ≠ 2</quote></p>
<p><strong>Not all applications are a great fit for React Native</strong> and that is why, <strong>at STRV, each application proposal is closely reviewed</strong> by our Frontend (React Native), iOS and Android departments to determine <strong>whether native or cross-platform development is the best fit</strong>. It is not uncommon for clients to approach us with a request for a complex React Native application and us suggesting native development instead, to ensure client and project success. On the other side of that, our Android and iOS departments sometimes suggest React Native on less feature-intensive projects to benefit from cross-platform development.</p>
<h2 id="the-state-of-react-native">The State of React Native</h2>
<p>To follow up on the statements above, it is worth mentioning that <strong>React Native is not just for simple applications.</strong> The framework is battle-tested by Facebook and Instagram applications, which regularly appear on the AppStore’s Top 10 Most Downloaded Apps in the US. And, recently, <a href="https://twitter.com/FEhrsam/status/1453536588453986306">Coinbase</a> — the biggest crypto exchange platform and a heavy React Native user — nabbed the #1 spot on the list. There are many other leading companies using React Native; you can learn more on the <a href="https://reactnative.dev/showcase">React Native website</a>.</p>
<p>Among those companies, <strong>Microsoft has started investing in the framework,</strong> with Skype and Office applications now written in React Native. And not only has Microsoft taken an active part in the new React Native versions’ release process, but it’s also been developing <a href="https://microsoft.github.io/react-native-windows/">react-native-windows</a> — a library to ease the development of desktop apps for both Windows and macOS. A great example of a successful approach is the rewrite of Facebook’s Messenger desktop app from Electron, the current cross-platform desktop go-to solution, to React Native. This goes hand in hand with React Native’s <a href="https://reactnative.dev/blog/2021/08/26/many-platform-vision">Many Platform Vision</a>. Some of the main motivations were also described in <a href="https://www.youtube.com/watch?v=9L4FFrvwJwY">a recent React Conf 2021 talk</a>.</p>
<h3 id="trends">Trends</h3>
<h4 id="shift-to-expo">Shift to Expo</h4>
<p>Looking at the applications currently under development at STRV, we have seen a <strong>major shift towards <a href="https://expo.dev/">Expo</a>,</strong> a React Native framework that tries to abstract out manipulation of native iOS and Android code to allow web engineers with knowledge of React to build mobile apps without major roadblocks. We were quite skeptical about Expo; just a year ago, <a href="https://www.strv.com/blog/what-i-learned-as-a-web-dev-on-my-first-react-native-project-engineering#:~:text=This%20is%20obviously,our%20clients%E2%80%99%20money.">I suggested that you can’t build a professional application</a> with it. Oh, how things change in frontend development…</p>
<p>The truth is that <strong>of our two new React Native projects, both are Expo applications</strong>. In both cases, the codebase was already bootstrapped by the client, so it was not exactly our choice — yet we’ve seen major improvements in the Expo ecosystem, which is why we decided to stay open-minded and give it a go. Additionally, keeping what’s best for our clients in mind, ejecting a project from the start would mean adding complexity with which the clients’ internal engineers might struggle in terms of productivity.</p>
<p>To add perspective, <strong>we generally</strong> <strong>had two big problems with Expo</strong> <strong>projects</strong>. The first was that whatever features you needed, once you shipped your application, Expo would bundle all its features with it — meaning that the <strong>resulting application size would be a minimum of 50MB</strong>, regardless of its simplicity.</p>
<p>The second was that, when integrating a package that was not part of the Expo environment, you would have to start managing everything Expo was doing previously for you — a <strong>painful process previously called</strong> “**ejecting.**” Therefore, it always made sense to build pure React Native applications from the start to offer the <strong>best customization for our clients and a small application size for their users</strong>.</p>
<p><strong>Neither of the arguments above holds true anymore</strong>. First, Expo introduced the <a href="https://blog.expo.dev/introducing-eas-395d4809cc6f">Expo Application Services (EAS) build system</a>, which bundles only features your application actually uses. Once we migrated a client&#39;s app from the previous Expo build system to EAS, the iOS <strong>application size dropped by 63%, from 70MB to 26MB</strong>.</p>
<p>Secondly, the changes in the build system enabled customization of Expo applications with a new <a href="https://blog.expo.dev/expo-managed-workflow-in-2021-d1c9b68aa10">config plugins environment</a>. Now, whenever we need to customize our React Native project the way traditional Expo would not allow us to, we can write an Expo config plugin that will do the customization for us. On my current project, I have five essential config plugins (three of my own, two community-driven) and another two from the community I use for development — proving that without customization, one would have to either eject from Expo or make sacrifices on certain features.</p>
<p>Moreover, <strong>EAS tremendously helps with credential management for submitting applications</strong> to app stores, which is a common pain point for a React Native engineer who has to learn specificities for both iOS and Android store submissions. Not everyone has the luxury of having colleagues from native departments nearby to offer their expertise (like we do at STRV).</p>
<p>Overall, Expo has made a huge leap forward in 2021 and I believe that slow convergence towards Expo will benefit the previously split community of React Native engineers who would develop only in Expo versus those who would prefer full control and would not give it a chance (which used to be our case). <strong>Standardization of React Native applications should also help the clients</strong>, making it easier to find and hire the right engineering candidates who will be maintaining the application and its codebase.</p>
<h3 id="competition">Competition</h3>
<p>There’s been quite a big hype around <a href="https://flutter.dev/">Flutter</a>, a cross-platform framework by Google. Its popularity has been growing rapidly, even catching the attention of our <a href="https://www.strv.com/blog/wrap-up-android-talks-with-motionlayout-vector-drawables-ml-kit-flutter-engineering-android">Android department</a>. These days, it is quite common to compare React Native to Flutter, with each side elevating its favorite framework. Yet the truth is that <strong>competition only benefits everyone</strong>.</p>
<p><strong>I believe that both frameworks can thrive and learn from each other</strong>. It might be a good thing that React Native is not the only major cross-platform player, should something extreme happen — like Apple considering limiting the presence of cross-platform applications.</p>
<p>For us, React Native is a battle-tested cross-platform solution that provides our clients a familiar codebase to work with. But we have also started actively utilizing <a href="https://kotlinlang.org/lp/mobile/">Kotlin Multiplatform</a>, an elegant cross-platform solution that allows our Android and iOS departments to share the business logic part of the codebase, offering time-saving and consistency across both applications.</p>
<h2 id="looking-ahead">Looking Ahead</h2>
<p>We have many things to be excited about in the React Native ecosystem. <strong>The major evolution coming in 2022 is most likely a release of a new rendering system called <a href="https://reactnative.dev/docs/fabric-renderer">Fabric</a></strong>, which has been in development since 2018 and, by the way, is already powering over 1,000 screens on your Facebook application.</p>
<p>Overall, <strong>React Native’s new architecture promises even better performance and application start-up times</strong>. A big part of this will also be Hermes, a javascript engine optimized for React Native originally built to speed up Android applications. Recently, it got the support of iOS and is on track to <a href="https://reactnative.dev/blog/2021/10/26/toward-hermes-being-the-default">become the new default</a>.</p>
<p>The new architecture release will coincide with <strong>React 18 bringing Suspense</strong>, a data fetching evolution that has been in the works for a few years. Together with Suspense, the new architecture will <strong>allow applications to not only be faster but feel faster</strong>.</p>
<p>The React Native community is also very active, and one of the most exciting projects within the space is <a href="https://www.youtube.com/watch?v=EHxEX78alZE">React Native Skia</a>, an implementation of Skia — Google’s 2D graphics engine powering Flutter applications (proving my point about competition benefits). Hopefully, we may see a stable release this year, allowing engineers to <strong>utilize new drawing capabilities and shift some graphics from less performant SVGs to Skia</strong>.</p>
<p>Another community project to watch is <a href="https://re-pack.netlify.app/">RePack</a>, a toolkit bringing <strong>Webpack</strong> — a module bundler — and its powerful ecosystem to React Native. It’s a much-needed competition to Metro, the current default bundler solution that has not seen a significant improvement compared to new web-based bundlers.</p>
<p>Finally, I would like to go back to Expo, which we will definitely see growing further. <a href="https://blog.expo.dev/eas-update-in-preview-d221b6f91f52">EAS Updates</a> — an evolution of Expo Updates — has just been released to preview, allowing developers to create <strong>workflows in which they can update mobile applications “over-the-air”</strong> without the need to go through the Apple or Google store review. It’s a total life-saver to instantly fix little bugs.</p>
<p>There are also <a href="https://blog.expo.dev/a-peek-into-the-upcoming-sweet-expo-module-api-6de6b9aca492">Expo Modules</a> in the works, which should allow us to write React Native packages in Swift (iOS) and Kotlin (Android). Those are easier programming languages to learn compared to Objective-C and Java, <strong>empowering more engineers in bringing native iOS and Android features to React Native</strong>.</p>
<h2 id="summary">Summary</h2>
<p>React Native has been evolving and it is encouraging to see both Facebook and Microsoft heavily investing in its future. Given its cost-saving potential and codebase familiarity and maintainability, it is an attractive option for those of our clients who frequently consider it as their solution of choice. Yet years of experience in architecting mobile applications and solutions <a href="https://www.strv.com/blog/strv-in-top-1-of-global-b2b-companies-2021-design-engineering">positions us</a> as a company that understands <strong>in which cases React Native can truly thrive, thereby letting us ensure the success of our clients’ applications</strong>.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React Native at STRV in 2023]]></title>
            <link>/posts/react-native-at-strv-in-2023</link>
            <guid>/posts/react-native-at-strv-in-2023</guid>
            <pubDate>Wed, 15 Feb 2023 08:00:00 GMT</pubDate>
            <description><![CDATA[In the current macroeconomic situation, React Native’s cost efficiency and speed of development are ever-attractive for our clients, yet one still has to be realistic and expect potential compromises and limits — which native iOS and Android solutions just do not have to face. That is why we are so excited about 2023 when, once again, many of those limits and compromises will be broken.]]></description>
            <content:encoded><![CDATA[<p>import Image from &#39;next/image&#39;</p>
<p>One year ago, I wrote a thorough review of the general state of the React Native cross-platform framework and its position at STRV. It’s time for a follow-up.</p>
<p><img src="/images/AronBreno.jpg" alt="Aron in STRV offices"></p>
<p><em><a href="https://www.strv.com">At STRV offices</a></em></p>
<p>Some of <a href="https://www.strv.com/blog/react-native-at-strv-in-2022-engineering">my predictions</a>, such as the framework&#39;s convergence to Expo and transition to the new architecture, have proven to be easy bets — but what I wouldn’t have predicted is the rise of React Native projects under our Frontend department development.</p>
<p>Over the last year, we have worked on <strong>a record 10 React Native projects</strong>, which demonstrates the <strong>ever-increasing demand from clients</strong> matched by our <strong>successful hiring.</strong></p>
<h2 id="2022-in-review">2022 in Review</h2>
<p>Looking back at 2022, there were quite a few notable events to mention.</p>
<h3 id="react-native-068">React Native 0.68</h3>
<p>Version 0.68 released in <strong>March</strong> was the first to include the <a href="https://reactnative.dev/blog/2022/03/30/version-068#opting-in-to-the-new-architecture">new architecture opt-in</a> flag, allowing everyone to get a taste of it and for community libraries maintainers to start experimenting with its adoption.</p>
<h3 id="appjs-conference-in-krakow">App.js Conference in Krakow</h3>
<p>After a long Covid break, the whole community finally gathered in <strong>June</strong> for a face-to-face conference to exchange ideas, share common struggles and get a peek at the future of React Native. STRV participated and confirmed that our development practices utilize the best React Native can offer.</p>
<p>Personally, I attended a new architecture workshop to get a better understanding of its <strong>adoption timeline</strong>. It was clear that it will be a bumpy road for the community since it’ll take <strong>at least two years</strong> before the architecture reaches wider adoption — but the commitment from Meta to support library maintainers going through the transition was reassuring.</p>
<p>We also attended an animations and React Native Skia workshop to up our skills in building performant and interactive user experiences, and to understand <strong>Skia’s capabilities</strong>.</p>
<p>Worth mentioning is that as a conference partner, <strong>Expo established itself as a React Native leader</strong> and re-introduced its new features, many of which we’d already been utilizing on STRV projects and which I also wrote about in my last article.</p>
<p>But the <a href="https://twitter.com/ImRestrepo/status/1537061094220615682">announcement that stole the show</a> was the introduction of <strong>Shopify’s Flashlist</strong>, a drop-in and significantly more performant replacement for the infamously slow Flatlist. The community’s <strong>excitement was like nothing I’d ever seen before</strong>; nobody had been expecting someone to provide a solution for one of the most common React Native issues — slow long lists — just like that, even before the new architecture had arrived.</p>
<h3 id="expo-router">Expo Router</h3>
<p>Another great innovation came from Expo in <strong>September</strong> in the form of <a href="https://blog.expo.dev/rfc-file-system-based-routing-in-react-native-7a35474722av">Expo Router’s initial beta release</a>. <strong>File-based routing</strong> is a feature that web developers take as a given; almost every major frontend framework supports it — yet only now, with Expo Router, can we utilize it to scale projects on mobile. I believe there are many more web features the router will unlock for mobile development but, most importantly, it will likely become an essential tool in building <strong>shared navigation between mobile and web in case of multi-platform applications</strong>.</p>
<h3 id="how-can-we-improve-react-native">How Can We Improve React Native?</h3>
<p>One positive surprise came in <strong>October</strong>, when <strong>Meta</strong> opened up an <a href="https://github.com/reactwg/react-native-new-architecture/discussions/105">active discussion</a> among the React Native community to figure out the biggest pain points, with core contributors to the framework acknowledging the issues and providing necessary visibility into their action plans. I believe the community finally feels heard and that this step <strong>strengthened the overall relationship between developers and Meta</strong> — especially during the crucial transition to the new architecture, where we just have to trust it will unlock the benefits we were promised.</p>
<h3 id="other-developments">Other Developments</h3>
<p>Also notable was the <strong>ever</strong>-<strong>increasing adoption</strong> of React Native, with <a href="https://twitter.com/discord/status/1554135644846395392?t=MhpAoe_0jDdq3AOdLSin3g&amp;s=19">Discord</a>, <a href="https://twitter.com/amasad/status/1582754714575257600?s=20&amp;t=p3Y-DH0NgvSw-MZAWjXJcA">Replit</a>, <a href="https://twitter.com/steam/status/1580275813429444609">Steam</a> and <a href="https://twitter.com/aarongrider/status/1593046460630994944?s=46&amp;t=uSTASFMukhGBMFftW9Y7_Q">Starlink</a> apps echoing most among the programming community. Even the <a href="https://microsoft.github.io/react-native-windows/blog/2022/02/11/settings">Windows 11 Settings</a> app is now using React Native, proving the framework&#39;s capabilities in what was otherwise a largely uneventful year for desktop support, with <a href="https://youtube.com/watch?v=639DW0kN28w&amp;si=EnSIkaIECMiOmarE">Microsoft</a> remaining the leader in the space.</p>
<p>And finally, at the end of 2022, we got our first <a href="https://survey.stateofreactnative.com/">State of React Native</a> <strong>survey</strong>. As I write this, the results are still pending.</p>
<h2 id="looking-ahead">Looking Ahead</h2>
<h3 id="new-architecture">New Architecture</h3>
<p><strong>2023 will be the year of a full-speed transition of common libraries to the new architecture</strong>. Yet as far as wider adoption among developers is concerned, I expect that to come <strong>in 2024.</strong></p>
<p>The current Expo SDK 47 — together with the new <a href="https://blog.expo.dev/expo-sdk-47-a0f6f5c038af#3791">Expo Modules API</a> — is paving the way for the seamless creation of libraries with support for the new architecture in mind, so I wonder how many maintainers will be tempted to abandon their existing solutions, choosing to create a new one from scratch. One common library, React Native Pager View, decided <a href="https://github.com/callstack/react-native-pager-view/issues/673#issue-1504983516">something in that sense</a>. Better than stitching together a new compatibility upgrade, <strong>the architecture transition is a good reason to reevaluate the project and start fresh</strong>.</p>
<p><strong>This is as exciting as it is worrying</strong>. The community will be required to keep a close eye on which versions of the library are still compatible with the old architecture until all essential ones have transitioned. <strong>We can’t use the new architecture unless all dependencies are compatible</strong>. One way to find libraries that already support the new architecture is <a href="https://reactnative.directory/?newArchitecture=true">reactnative.directory</a>.</p>
<p>At STRV, we will monitor the community closely to keep ourselves informed so that we can prevent potential incompatibilities on our projects. And with the progressing adoption, we will start building a demo application based on the new architecture to test common functionalities and to serve as <strong>a benchmark for our own adoption</strong>.</p>
<h3 id="react-native-web-renaissance">React Native Web Renaissance?</h3>
<p>Besides the typical cost efficiency and speed of development reasons, our clients also choose React Native as a mobile solution due to <strong>its potential to share business logic with the web</strong>. Moreover, if there’s already a working website in React, <strong>the client&#39;s own developers can eventually become the maintainers</strong> of the React Native application we deliver.</p>
<p>In cases when we deliver a website (e.g., landing page, mobile app web equivalent, admin), node backend and a mobile application, <strong>monorepos have practically become the norm for STRV</strong>, with their utilization in many React and React Native projects. While they add <strong>complexity early on</strong> — especially for new adopters — <strong>the</strong> <strong>investment usually pays off</strong> by sharing simple things like various constants, translations and input validation rules, as well as more complex business logic and API.</p>
<p>Yet it’s always tempting to push code sharing even further and utilize React Native capabilities to <strong>build both mobile and web applications from a single codebase</strong>. While many websites already utilize the solution, developers working on those projects usually face <strong>problems and complexities</strong> trying to make their code performant, compatible, functional and accessible on all platforms. As you can imagine, these developers are usually not the happiest ones and actually, their <strong>retention becomes a big risk</strong> given their mobile and web know-how accumulation.</p>
<p>React Native Web is a good representation of all the high hopes developers put into React Native; yet instead of them being fulfilled, it has often led to <strong>misuse of the framework</strong> — resulting in many developers getting burned and vowing not to touch it again. But with the latest innovations around the corner, even the hardest deniers may come back to give it <strong>one more chance</strong>.</p>
<p>At STRV, <strong>we reevaluate the multi-platform approach every year</strong> and scan the landscape for solutions that would make it easier to develop and maintain. Though <strong>still too early for production</strong>, 2023 finally feels like we may experience the <strong>React Native Web</strong> <strong>renaissance</strong> with new solutions for sharable routing and UI. The above-mentioned <a href="https://blog.expo.dev/announcing-the-expo-router-v1-release-candidate-c5680b88a18c">Expo Router</a> has the potential to provide <strong>unified routing for both web and mobile</strong>, and the recent release of <a href="https://tamagui.dev/blog/version-one">Tamagui v1.0</a> offers a <strong>performant, shareable UI and styling</strong> solution. Moreover, <a href="https://reactnative.dev/blog/2023/01/12/version-071#web-inspired-props-for-accessibility-styles-and-events">React Native 0.71</a> brings many web and mobile API unification improvements, answering the community’s demand for <strong>reduced compromises</strong> which are inevitable when building web with React Native. Let’s try and see.</p>
<h3 id="all-in-expo">All-in-Expo</h3>
<p>At STRV, we’ve pretty much moved all React Native development to the modern Expo set of tools, starting with Expo <a href="https://docs.expo.dev/development/create-development-builds/">dev clients</a> and <a href="https://docs.expo.dev/guides/config-plugins/">config plugins</a> for bringing any iOS or Android dependencies, all the way to <a href="https://expo.dev/eas">Expo Application Services</a> (EAS) — allowing fast builds and credentials management. While I wrote about it as a <a href="https://www.strv.com/blog/react-native-at-strv-in-2022-engineering#trends">trend for 2022</a>, 2023 shows that it’s undeniably become the <strong>most efficient</strong> way to build a React Native application.</p>
<p>With a clearly defined path forward, our team will finally be focusing on <strong>establishing best practices and a knowledge base</strong> for React Native development, subsequently sharing it with our team members.</p>
<h3 id="more-conferences--meetups">More Conferences &amp; Meetups</h3>
<p>In 2023, the community will benefit from <strong>two</strong> face-to-face <strong>conferences</strong>: <strong>App.js</strong> (May 10-12) in Krakow, which is expected to be a blast like last year, and <strong>Chain React</strong> (May 17-19) in Portland, Oregon, which is returning after a long break.</p>
<p>Thanks to the high demand for React Native projects, we have also decided to share our newly gathered know-how and <strong>organize two meetups ourselves</strong>, one in Brno (Feb. 14) and one in Prague (Feb. 16).</p>
<h3 id="everything-else">Everything Else</h3>
<p>React Native Skia has been actively <a href="https://shopify.engineering/react-native-skia-2022">developed</a> and this year, we might get V1 and see bigger adoption. The new architecture is expected to unlock many innovations, from much faster <a href="https://github.com/reactwg/react-native-new-architecture/discussions/105">Android and iOS builds</a> to even faster list libraries, such as <a href="https://twitter.com/margelo_io/status/1519021945295151109">WishList</a>. Bundling in React Native has been ripe for innovation and it finally seems that the default <a href="https://github.com/react-native-community/discussions-and-proposals/discussions/546#discussioncomment-4166119">Metro bundler will get improvements</a>. <a href="https://docs.expo.dev/versions/unversioned/sdk/image/">Expo-image</a> is going to bring modern image formats and loading techniques the web has utilized for years already. All in all, <strong>speed is the common denominator</strong>.</p>
<h2 id="summary">Summary</h2>
<p>While the longevity of frontend technologies is always in question, <strong>React Native is here to stay</strong>. With strong investments from Meta, Microsoft and Shopify, the best is yet to come. In the current macroeconomic situation, React Native’s <strong>cost efficiency and speed of development are ever-attractive for our clients,</strong> yet one still has to be <strong>realistic</strong> and expect potential compromises and limits — which native iOS and Android solutions just do not have to face. That is why we are so excited about 2023 when, once again, <strong>many of those limits and compromises will be broken</strong>.</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What I Learned as a Web Dev on My First React Native Project]]></title>
            <link>/posts/what-i-learned-as-a-web-dev-on-my-first-react-native-project</link>
            <guid>/posts/what-i-learned-as-a-web-dev-on-my-first-react-native-project</guid>
            <pubDate>Thu, 18 Feb 2021 08:00:00 GMT</pubDate>
            <description><![CDATA[What was your first year like when you started your coding career? I remember it went quite smoothly for me, and I jumped onto a project pretty early on. It was...]]></description>
            <content:encoded><![CDATA[<h1 id="what-i-learned-as-a-web-dev-on-my-first-react-native-project">WHAT I LEARNED AS A WEB DEV ON MY FIRST REACT NATIVE PROJECT</h1>
<p>What was your first year like when you started your coding career? I remember it went quite smoothly for me, and I jumped onto a project pretty early on. It was an ongoing project—so time to market wasn&#39;t a key factor—and I got great support from my colleagues. But let&#39;s face it: With older projects, you mostly deal with bugs, optimizations and continued refactoring, plus some features here and there.</p>
<p>Refactoring did actually keep my motivations high by opening up a path for learning how to write better code. Yet as a junior dev, it is essential to try new things to get a <strong>greater perspective</strong>; that&#39;s what helps you answer questions about your career, coding preferences or favorite libraries—which is the core of most fun arguments with your colleagues.</p>
<p>Therefore, when I hit one year in my coding career, it was a proper challenge and blessing in one when a new project came around—specifically a <strong>React Native (RN) project</strong>. Just like that, together with my senior colleague, I started building a new <strong>mobile</strong> app for iOS and Android using my <strong>web development skills</strong>. Meaning that my previous article should be renamed to <a href="https://www.strv.com/blog/how-i-left-a-financial-markets-career-for-web-development-insidestrv-engineering">How I Left a Financial Markets Career for <del>Web</del> Frontend Development</a>. And, as in the previous article, this experience has come with plenty of lessons worth sharing.</p>
<h2 id="getting-started">GETTING STARTED</h2>
<p>While the React Native coding environment feels quite familiar to a React developer, <strong>you actually lack the knowledge of what you are able to build with your skills.</strong> Here is where the afore-mentioned greater perspective comes into play; as a developer, you need to broaden your horizons—otherwise, you are risking living in your small bubble, fearing change and getting stuck.</p>
<h3 id="learning">Learning</h3>
<p>Perpetually finding myself in somewhat of a &quot;code newbie&quot; mindset, I know that there are certain gaps in my coding skills that I need to fill.</p>
<p>I always prefer learning by actually seeing someone building something. At the time of this project, my favorite tutor, Mosh Hamedani, had released his React Native <a href="https://www.youtube.com/watch?v=0-S5a0eXPoc">course</a> (free YouTube preview), so I signed up for it and built my first app. Besides the app building and his coding tips, the great thing about Mosh&#39;s course is that he walks you through the setup of Xcode and Android Studio, which are needed for using mobile device emulators/simulators. You want to get this right. But do not worry, we can still write our code in, for example, VSCode.</p>
<p>Another great tutor, The Net Ninja, has a free <a href="https://www.youtube.com/watch?v=ur6I5m2nTvk&amp;list=PL4cUxeGkcC9ixPU-QkScoRBVxtPPzVjrQ">course</a> also worth checking out. And finally, I&#39;ve discovered William Candillon, who is a big guru in the React Native community especially thanks to his &quot;<a href="https://www.youtube.com/watch?v=-PEaIQb09oQ&amp;list=PLkOyNuxGl9jxB_ARphTDoOWf5AE1J-x1r&amp;index=10">Can it be done in React Native?</a>&quot; YouTube series. While William is mostly focused on animations, around that time he also started a series called <a href="https://www.youtube.com/watch?v=MqRnpUC4czs&amp;list=PLkOyNuxGl9jyhndcnbFcgNM81fZak7Rbw&amp;index=25">&quot;React Native Fashion&quot;</a>, where he builds an app from scratch based on designs in Figma—which is very close to the real developer experience, so check it out!</p>
<h3 id="expo-vs-react-native-cli">Expo vs. React Native CLI?</h3>
<p>You will find that almost all tutorials, be it the ones from YouTube or Medium, will use <a href="https://docs.expo.io/">Expo</a>, a framework and set of tools for building React Native applications. Its &quot;managed&quot; workflow prevents and eases many headaches React Native developers face. Expo apps are super easy to set up and are made available on your mobile device through a simple Expo client, meaning it skips the App Store and Play Store in the process. This is obviously <strong>a great choice for a tutorial or an MVP, but is it good for a professionally built app</strong>?</p>
<p>For now, it usually isn&#39;t! Expo does not allow you to touch native Android and iOS modules and, in general, you are <strong>locked to their environment</strong> — which is very powerful, but the situation is still not ideal. If you&#39;d need something that is not available in Expo, you would have to go through a potentially painful ejecting process. Also worth mentioning is that Expo apps are significantly bigger in size. At STRV, we always use <strong>React Native CLI to build apps so that we can provide the best value for our clients&#39; money.</strong></p>
<p>Many tutors and commentators heavily promote Expo and scare new developers by claiming that with React Native CLI, devs will have to touch native iOS and Android modules to get things working. But in reality, those are big scares of the past. Since React Native version 0.60, almost all libraries are auto-linked and you just have to install them with npm or yarn. I imagine that before that time, it was probably a huge headache; but now, already close to version 0.64, things are much better. Though, yes, there are cases when you have to play around with native modules—for example, to set up a splash screen and an app icon—but, again, you are a developer and, sometimes, you need to get your hands dirty. <strong>Avoiding difficult things may just create internal anxiety that will surface later.</strong></p>
<h2 id="the-development-experience">THE DEVELOPMENT EXPERIENCE</h2>
<p>It is different. Once you set up your Android Emulator and iOS Simulator, you can start exploring your code changes—and will soon discover that not everything is as simple as it is in tutorials.</p>
<h3 id="does-it-work-on-both-android-and-ios">Does It Work on Both Android and iOS?</h3>
<p>As a web dev, you check how your app behaves across various internet browsers. In mobile development, you check <strong>if things are working in the same way on both Android and iOS.</strong> This is important. There are some libraries or component properties that are platform-specific only. Documentation is your friend, so keep it in mind. It can literally be trivial things—like shadow properties that have no effect on Android, because you&#39;ll have to utilize preset <a href="https://reactnative.dev/docs/view-style-props#elevation">elevation</a> properties.</p>
<h3 id="how-does-it-look-on-my-old-nexus-versus-iphone-12">How Does It Look on My Old Nexus Versus Iphone 12?</h3>
<p>Another parallel is checking for website responsiveness while resizing the browser screen versus checking how your app looks on mobile devices with various screen sizes and pixel density. <strong>This can easily lead to misaligned design.</strong> If your simulator is big enough and fits all things on one screen, it may require a <a href="https://reactnative.dev/docs/using-a-scrollview">ScrollView</a> component on a smaller device to allow users to reach all the offscreen content.</p>
<h3 id="debugging">Debugging</h3>
<p>There are many ways to debug your app by reaching for tools like React Dev Tools, a simple element inspector or a network tab that you&#39;re used to. Tools such as <a href="https://github.com/jhen0409/react-native-debugger">React Native Debugger</a> are also quite popular, but they require turning on the &#39;<strong>Remote debugging</strong>&#39; mode on your simulator, which I found sometimes interferes with the app and throws weird errors.</p>
<p>With React Native version 0.62 comes <a href="https://fbflipper.com/docs/features/react-native/">Flipper</a>, Facebook&#39;s own debugging tool <strong>included as a default</strong> for you to use. This is great because it works out of the box and you just need to enable plugins for your app to get it working. Maybe the UI is not the nicest you would expect (luckily, it is being improved), but having it built in and not interfering with your app is a great plus.</p>
<p>Also, if your build is failing, sometimes it is worth turning on Xcode and Android Studio to build your app there, as their logs may better point you to what is causing the issue. I know, those tools feel like a blackbox and your working machine will surely start loudly complaining, but some familiarity will pay off. Check, for example, this <a href="https://www.youtube.com/watch?v=wVJxb36wjjA">talk</a> on Xcode.</p>
<p>To be honest, <strong>debugging errors will take a long time to get used to.</strong> For a novice, it is not always apparent where the error is coming from. And, more importantly, it&#39;ll take time to figure out if code changes alone can fix the issue, or if you have to reload—or even rebuild—your app. This can make you lose precious time, which is why I recommend documenting the steps you take when resolving common bugs—that&#39;s how you will save time later on.</p>
<h3 id="fast-refresh">Fast Refresh</h3>
<p>When things are going quite smoothly, something I really enjoy is <a href="https://reactnative.dev/docs/fast-refresh">Fast Refresh</a>, which allows you to see your code changes reflected instantly. Some great news is that this functionality has recently made its way to web development as well.</p>
<h2 id="coding-tips">CODING TIPS</h2>
<p>There&#39;s quite a lot to consider when you are building a mobile app in React Native after having worked solely in web development. As such, in this section I would like to touch on a few essential topics that you may find helpful.</p>
<h3 id="styling">Styling</h3>
<p>All your components are <code>display: flex</code> and <code>flexDirection: column</code> as default, so forget grids and blocks and brush up on your flexbox skills. You will often be tempted to use <code>flex: 1</code> to make your container fill the whole screen or all available space, which is perfectly fine—but remember that these don&#39;t have to play nicely if your component has any animation elements and the device has to recalculate the space. Similarly, another default is <code>position: relative</code>, meaning your absolute elements are positioned relative to their parent.</p>
<p>Forget CSS pseudo-elements and selectors; in React Native, <strong>we inline the styles.</strong> The recommended approach is to use a StyleSheet object, but I enjoy using Styled Components in a similar way as on the web. If you are a fan of styled systems, <a href="https://github.com/Shopify/restyle">Restyle</a> from Shopify is gaining popularity.</p>
<p>You can also choose from several <strong>UI kits</strong> to get started on your hobby project. Popular ones are, for example, <a href="https://callstack.github.io/react-native-paper/">React Native Paper</a> and <a href="https://akveo.github.io/react-native-ui-kitten/">UI Kitten</a>.</p>
<p>By the way, remember that you don&#39;t have semantic HTML elements at your disposal. Most components are View (container) or Text (you cannot use simple text with other components), therefore you may want to think about adding some <strong>accessibility props</strong>.</p>
<h3 id="images">Images</h3>
<p>You cannot use .svg files as a source for RN&#39;s Image component. You will probably end up using pngs, ideally 3x the size to account for iPhones&#39; scale factor—so don&#39;t forget to compress it! If you want to use svgs, use <a href="https://github.com/react-native-svg/react-native-svg">React-Native-SVG</a> library and <a href="https://react-svgr.com/playground/">SVGR</a> playground for quick conversion to an RN component.</p>
<h3 id="animations">Animations</h3>
<p>You can use the built-in <a href="https://reactnative.dev/docs/animations">Animated</a> API, which performs well especially when using <code>useNativeDriver: true</code> prop. However, you get the best performance with the <a href="https://github.com/software-mansion/react-native-reanimated">React-Native-Reanimated</a> library, which is currently being upgraded to version 2 and expectations are high! Note that this only works with Hermes enabled (see the next section). More sophisticated animations used to, for example, wow users with an eye-catching splash screen, are commonly achieved with <a href="https://airbnb.design/lottie/">Lottie</a>.</p>
<h3 id="libraries">Libraries</h3>
<p>In general, there are actually many built-in <a href="https://reactnative.dev/docs/components-and-apis">components </a>within React Native. For example, Activity Indicator (loader) that behaves natively on both Android and iOS, or Flatlist, a component used to display and optimize lists of items, a preferred way compared to mapping over an array as we are used to from the web. The trend is to make the RN library lighter, which is why some nonessential ones were moved to <a href="https://github.com/react-native-community">React Native Community</a> repo for maintenance.</p>
<p>One important note for Android: As you add more libraries, you may encounter an error that limits you to a certain number of allowed methods. To deal with this, enable <a href="https://developer.android.com/studio/build/multidex">Multidex</a>. Another error may come if you enable <a href="https://reactnative.dev/docs/hermes">Hermes</a>, an optimized Javascript engine for running Android apps and, soon, also <a href="https://github.com/react-native-community/releases/issues/214">iOS</a>. While some libraries—like the above-mentioned Reanimated—require it, others are not yet compatible with it (Realm - see below).</p>
<h3 id="keyboard-avoiding-view">Keyboard Avoiding View</h3>
<p>No comment. If you&#39;ve worked with React Native, you get this. It is a topic one would rather skip. When you work with text inputs, <strong>you have to account for the keyboard sliding from the bottom</strong>, hence we utilize the <a href="https://reactnative.dev/docs/keyboardavoidingview">Keyboard Avoiding View</a> container that is able to adjust itself and make space for the keyboard. Unfortunately, consistency across iOS and Android is not always there, and you will probably end up adjusting Android&#39;s <a href="https://developer.android.com/training/keyboard-input/visibility">windowSoftInputMode</a> at some point to get the best experience.</p>
<h3 id="landscape-mode">Landscape Mode</h3>
<p>Another unpleasant thing you might face is optimizing for the landscape mode. For most apps, it is common practice to just disable it.</p>
<h3 id="navigation">Navigation</h3>
<p>To navigate between screens, you will probably end up using the very popular <a href="https://reactnavigation.org/">React Navigation</a> library. There is a great, purely native alternative, <a href="https://github.com/wix/react-native-navigation">React Native Navigation</a> (the names get confused easily), from Wix. It is super performant but not that flexible. Therefore, again: If your design asks you for something custom, you have no choice but to go with React Navigation; luckily, it is a great, well-documented option.</p>
<h3 id="storing-data">Storing Data</h3>
<p>The Redux library is quite a common choice thanks to its broad ecosystem. Luckily, there is now a very useful <a href="https://redux-toolkit.js.org/">Redux Toolkit</a> that mitigates the amount of boilerplate you have to usually write. <a href="https://github.com/rtk-incubator/rtk-query">RTK Query</a> is a very new Redux solution for data fetching and caching, hopefully making our lives even easier. Though the web seems to slowly be moving away from Redux to React Query, SWR or other solutions, mobile is a different story; Redux is holding on to its popularity, as it integrates well with <a href="https://github.com/rt2zz/redux-persist">libraries</a> that persist and rehydrate the global state for users when they relaunch the app.</p>
<p>To persist data on the device, it is common to use <a href="https://github.com/react-native-async-storage/async-storage">AsyncStorage</a>, which is an asynchronous alternative to web&#39;s LocalStorage. Another interesting option (though a bit more complex) is to use the <a href="https://realm.io/docs/javascript/latest/">Realm</a> database.</p>
<h3 id="other-mobile-development-considerations">Other Mobile Development Considerations</h3>
<p>Sooner or later, you will encounter a situation where you need to add permissions to your app; for example, to access the camera and photos library during a file upload. Though not always required, it is common to use the <a href="https://github.com/zoontek/react-native-permissions">React Native Permissions</a> library to offer a consistent experience across platforms.</p>
<p>Further, mobile devices can lose connectivity easily; for that, you can count on the <a href="https://github.com/react-native-netinfo/react-native-netinfo">NetInfo</a> library to offer a user experience while offline. Finally, notifications are an essential part of mobile apps and <a href="https://rnfirebase.io/">Firebase</a> offers great React Native integrations.</p>
<h2 id="final-words">FINAL WORDS</h2>
<p>We live in an amazing time. Our React coding skills can easily transfer from web to mobile to build full-fledged iOS and Android apps. Sometimes, this allows us to offer significant cost savings to our clients in the process. Yet one has to understand that mobile and web development do differ and, to offer a great user experience, it is not only about the code we write.</p>
<p>Experienced mobile app developers can easily smell when something is not right, therefore I insist that you put your ego aside and ask them—be it your colleagues or peers on Twitter or Reddit, or anyone with mobile UX know-how—to review your app and provide feedback. Only with this approach can you progress and apply your skills to build great products.</p>
]]></content:encoded>
        </item>
    </channel>
</rss>