<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Áron Berezkin</title>
    <description>The latest articles on DEV Community by Áron Berezkin (@aronberezkin).</description>
    <link>https://dev.to/aronberezkin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F535275%2F23157e85-3c07-42c3-812a-676bfa690c76.png</url>
      <title>DEV Community: Áron Berezkin</title>
      <link>https://dev.to/aronberezkin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aronberezkin"/>
    <language>en</language>
    <item>
      <title>How to Integrate Plaid SDK to React Native Using Expo Config Plugins</title>
      <dc:creator>Áron Berezkin</dc:creator>
      <pubDate>Thu, 30 Dec 2021 16:38:15 +0000</pubDate>
      <link>https://dev.to/aronberezkin/how-to-integrate-plaid-sdk-to-react-native-using-expo-config-plugins-33dg</link>
      <guid>https://dev.to/aronberezkin/how-to-integrate-plaid-sdk-to-react-native-using-expo-config-plugins-33dg</guid>
      <description>&lt;p&gt;Previously, if you wanted to integrate &lt;a href="https://github.com/plaid/react-native-plaid-link-sdk" rel="noopener noreferrer"&gt;Plaid React Native SDK&lt;/a&gt; to Expo, you either had to forcefully eject to bare workflow or use a &lt;a href="https://github.com/burstware/expo-plaid-link" rel="noopener noreferrer"&gt;webview solution&lt;/a&gt; which could result in some funny unexpected issues such as &lt;a href="https://github.com/burstware/expo-plaid-link/issues/15" rel="noopener noreferrer"&gt;this recaptcha pop up&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Well, in case you have stumbled upon my previous guide to &lt;a href="https://www.aronberezkin.com/posts/a-step-by-step-guide-to-writing-your-first-expo-config-plugin" rel="noopener noreferrer"&gt;Expo config plugins&lt;/a&gt;, 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 &lt;a href="https://plaid.com/" rel="noopener noreferrer"&gt;Plaid&lt;/a&gt;, a reliable service to connect financial accounts to our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  SETUP
&lt;/h2&gt;

&lt;p&gt;To get started you can use &lt;a href="https://github.com/AronBe/article-expo-plaid-config-plugin" rel="noopener noreferrer"&gt;this Github repository&lt;/a&gt; as a starter or just follow these commands:&lt;/p&gt;

&lt;p&gt;Initiate a new Expo project - here with typescript for better DX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo init expo-plaid-sdk-integration  &lt;span class="nt"&gt;-t&lt;/span&gt; expo-template-blank-typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the React Native Plaid SDK library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add react-native-plaid-link-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;App.tsx&lt;/code&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PlaidLink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LinkSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LinkExit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-plaid-link-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PlaidLink&lt;/span&gt;
        &lt;span class="na"&gt;tokenConfig&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#GENERATED_LINK_TOKEN#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;noLoadingState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LinkSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LinkExit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add Account&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;PlaidLink&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And include iOS bundleIdentifier and Android package name of your choice to &lt;code&gt;app.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"expo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...otherProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"supportsTablet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bundleIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.expo.plaid"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"android"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"adaptiveIcon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"foregroundImage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./assets/adaptive-icon.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FFFFFF"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"package"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.expo.plaid"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now try running the application through Expo Go, you will likely see this error...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;TypeError: null is not an object (evaluating '_reactNative.NativeModules.RNLinksdk.continueFromRedirectUriString')&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;...which should be expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  PLAID INTEGRATION
&lt;/h2&gt;

&lt;p&gt;To start integrating Plaid we will need to run the app through &lt;a href="https://docs.expo.dev/development/getting-started/" rel="noopener noreferrer"&gt;expo-dev-client&lt;/a&gt; which we can achieve either by using &lt;code&gt;expo run&lt;/code&gt; &lt;a href="https://blog.expo.dev/introducing-expo-run-commands-835ae8da4813" rel="noopener noreferrer"&gt;commands&lt;/a&gt; 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 &lt;code&gt;run&lt;/code&gt; commands. Then we just need to follow the Plaid &lt;a href="https://github.com/plaid/react-native-plaid-link-sdk" rel="noopener noreferrer"&gt;readme&lt;/a&gt; setup guide for both iOS and Android.&lt;/p&gt;

&lt;h3&gt;
  
  
  iOS setup
&lt;/h3&gt;

&lt;p&gt;This is actually super simple. The readme suggests adding to &lt;code&gt;ios/Podfile&lt;/code&gt; following string &lt;code&gt;pod 'Plaid', '~&amp;gt; &amp;lt;insert latest version&amp;gt;&lt;/code&gt; 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 &lt;code&gt;expo-dev-client&lt;/code&gt; by running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;After the build process finishes, the app launches without the error we experienced previously. You can press &lt;code&gt;Add Account&lt;/code&gt; and you should see Plaid error complaining about the token we provided - but about that later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Unexpected environment string value: (null). Expected one of: production, sandbox, or development.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Android setup
&lt;/h3&gt;

&lt;p&gt;If you run &lt;code&gt;expo run:android&lt;/code&gt; and press &lt;code&gt;Add Account&lt;/code&gt; at this stage, you will get an unhandled promise rejection..&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;TypeError: null is not an object (evaluating '_reactNative.NativeModules.PlaidAndroid.startLinkActivityForResult')&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;..because there are actually bunch of steps to make Android work and as the &lt;a href="https://github.com/plaid/react-native-plaid-link-sdk#android-setup" rel="noopener noreferrer"&gt;readme&lt;/a&gt; suggests it is due to TurboModules not supporting autolinking. But in general this is nothing we cannot setup ourselves with Expo config plugins.&lt;/p&gt;

&lt;h4&gt;
  
  
  1) Setup your app id
&lt;/h4&gt;

&lt;p&gt;This change you have to do on Plaid Dashboard at the &lt;code&gt;API&lt;/code&gt; &lt;a href="https://dashboard.plaid.com/team/api" rel="noopener noreferrer"&gt;page&lt;/a&gt; - &lt;code&gt;Allowed Android Package&lt;/code&gt;. You should configure there the Android package name from &lt;code&gt;app.json&lt;/code&gt; - &lt;code&gt;com.expo.plaid&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2) Update MainApplication.java
&lt;/h4&gt;

&lt;p&gt;Here we have to fullfil 2 requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Add import com.plaid.PlaidPackage; to the imports section&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Add packages.add(new PlaidPackage()); to List&amp;lt;ReactPackage&amp;gt; getPackages();&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which we can do only with an &lt;strong&gt;expo config plugin&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Create in the root of your project &lt;code&gt;withAndroidPlaid.ts&lt;/code&gt; file and start transpiling it to javascript with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn tsc withAndroidPlaid.ts &lt;span class="nt"&gt;--watch&lt;/span&gt; &lt;span class="nt"&gt;--skipLibCheck&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and import it in &lt;code&gt;app.json&lt;/code&gt; as a plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...otherProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./withAndroidPlaid"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, change &lt;code&gt;withAndroidPlaid.ts&lt;/code&gt; content to following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConfigPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@expo/config-plugins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withMainApplication&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@expo/config-plugins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applyPackage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mainApplication&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plaidPackageImport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`import com.plaid.PlaidPackage;\n`&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plaidAddPackage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`packages.add(new PlaidPackage());`&lt;/span&gt;

  &lt;span class="c1"&gt;// Make sure the project does not have the settings already&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;mainApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plaidPackageImport&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mainApplication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mainApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="sr"&gt;/package com.expo.plaid;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;`package com.expo.plaid;\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;plaidPackageImport&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;mainApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plaidAddPackage&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mainApplication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mainApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="sr"&gt;/return packages;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;`
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;plaidAddPackage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
    return packages;
    `&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mainApplication&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withAndroidPlaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expoConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withMainApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;applyPackage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;expoConfig&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withAndroidPlaid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look closely, our plugin is utilizing &lt;code&gt;withMainApplication&lt;/code&gt;, a &lt;a href="https://docs.expo.dev/guides/config-plugins/#mod-plugins" rel="noopener noreferrer"&gt;mod&lt;/a&gt; provided by Expo allowing us to read and modify the content of &lt;code&gt;MainApplication.java&lt;/code&gt;. We provide the content to our function &lt;code&gt;applyPackage&lt;/code&gt; where we execute 2 string replacements to insert &lt;code&gt;plaidPackageImport&lt;/code&gt; and &lt;code&gt;plaidAddPackage&lt;/code&gt; constants into the file - the changes Plaid readme wanted from us.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Our strategy is to simply find a stable part of the file where we can append our changes. Due to the string replacement nature, &lt;strong&gt;it is quite dangerous thing to rely on, because they could change with consequent React Native and Expo updates&lt;/strong&gt; - so be sure these replacements still work when you upgrade.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you run &lt;code&gt;expo prebuild -p android&lt;/code&gt; you should now see updated &lt;code&gt;MainApplication.java&lt;/code&gt;. If you did something incorrectly, you may want to discard changes, check your plugin code, and try &lt;code&gt;prebuild&lt;/code&gt; again.&lt;/p&gt;

&lt;h4&gt;
  
  
  3) Update app/build.gradle
&lt;/h4&gt;

&lt;p&gt;We need to update dependencies to following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="nf"&gt;project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;native&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plaid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which we can do utilizing &lt;code&gt;withAppBuildGradle&lt;/code&gt; modifying the file within &lt;code&gt;withAndroidPlaid&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nx"&gt;expoConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withAppBuildGradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;applyImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;applyImplementation&lt;/code&gt; is our custom function following the previous strategy of appending &lt;code&gt;plaidImplementation&lt;/code&gt; string to the right place of the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applyImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appBuildGradle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plaidImplementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`implementation project(':react-native-plaid-link-sdk')`&lt;/span&gt;

  &lt;span class="c1"&gt;// Make sure the project does not have the dependency already&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;appBuildGradle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plaidImplementation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;appBuildGradle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="sr"&gt;/dependencies&lt;/span&gt;&lt;span class="se"&gt;\s?&lt;/span&gt;&lt;span class="sr"&gt;{/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;`dependencies {
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;plaidImplementation&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;appBuildGradle&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4) Update settings.gradle
&lt;/h4&gt;

&lt;p&gt;Finally, we have to append following string to &lt;code&gt;settings.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;native&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plaid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;native&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plaid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;projectDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;projectDir&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;../&lt;/span&gt;&lt;span class="n"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;native&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plaid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which can be done using &lt;code&gt;withSettingsGradle&lt;/code&gt; Expo mod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withSettingsGradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;applySettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And making the changes with our custom &lt;code&gt;applySettings&lt;/code&gt; function. Notice that we are just concatenating the strings with &lt;code&gt;plus&lt;/code&gt; symbol given that we don't really care about the exact placement of &lt;code&gt;plaidSettings&lt;/code&gt; constant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applySettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gradleSettings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plaidSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`include ':react-native-plaid-link-sdk'
  project(':react-native-plaid-link-sdk').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-plaid-link-sdk/android')`&lt;/span&gt;

  &lt;span class="c1"&gt;// Make sure the project does not have the settings already&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;gradleSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`include ':react-native-plaid-link-sdk'`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;gradleSettings&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;plaidSettings&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;gradleSettings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you lost track of the changes or applied them incorrectly, you can always go to the solution branch of &lt;a href="https://github.com/AronBe/article-expo-plaid-config-plugin/tree/solution" rel="noopener noreferrer"&gt;this github repository&lt;/a&gt; for my final implementation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Troubleshooting&lt;/strong&gt;: 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: &lt;a href="https://github.com/plaid/react-native-plaid-link-sdk/issues/392#issuecomment-868857758" rel="noopener noreferrer"&gt;Kotlin version&lt;/a&gt; and &lt;a href="https://github.com/plaid/react-native-plaid-link-sdk/issues/146#issuecomment-648286809" rel="noopener noreferrer"&gt;OkHttp version&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After applying all necessary changes you should just run &lt;code&gt;expo run:android&lt;/code&gt; to build the app with all modifications.&lt;/p&gt;

&lt;p&gt;Once the build process finishes and the app launches, you can press &lt;code&gt;Add Account&lt;/code&gt; and you should see a different Plaid error complaining about configuration - but it is actually about the fake token we have provided.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;null - unable to open link, please check that your configuration is valid&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Getting the link token
&lt;/h3&gt;

&lt;p&gt;At this point, you just need to provide a correct link token in &lt;code&gt;App.tsx&lt;/code&gt;. Normally you would get it from your backend, but for testing purposes we can actually use a very handy &lt;a href="https://github.com/plaid/plaid-postman" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt; provided by Plaid.&lt;/p&gt;

&lt;p&gt;After going through the setup and utilizing your &lt;code&gt;client_id&lt;/code&gt; and &lt;code&gt;secret&lt;/code&gt; from Plaid dashboard, you can hit &lt;code&gt;https://sandbox.plaid.com/link/token/create&lt;/code&gt; API endpoint and use the returned &lt;code&gt;link_token&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expiration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2021-12-25T19:49:22Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"link_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"link-sandbox-965dbc89-14fc-4122-b900-27a562de6db0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AEBgG6EbWGsQ9aR"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now pressing &lt;code&gt;Add Account&lt;/code&gt; should finally open Plaid interface:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  SUMMARY
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>tutorial</category>
      <category>react</category>
    </item>
    <item>
      <title>How to Integrate Biometrics in React Native - Overview of 3 Approaches</title>
      <dc:creator>Áron Berezkin</dc:creator>
      <pubDate>Tue, 21 Dec 2021 15:17:00 +0000</pubDate>
      <link>https://dev.to/aronberezkin/how-to-integrate-biometrics-in-react-native-overview-of-3-approaches-p62</link>
      <guid>https://dev.to/aronberezkin/how-to-integrate-biometrics-in-react-native-overview-of-3-approaches-p62</guid>
      <description>&lt;p&gt;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 right away because you need to find a solution that fits both Android and iOS. Therefore, some due diligence is needed first.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Due diligence is an investigation, audit, or review performed to confirm facts or details of a matter under consideration."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are several criteria you have to consider. &lt;strong&gt;Biometrics is usually a feature utilized in security-heavy focused applications to authenticate users&lt;/strong&gt;; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Biometrics is also meant to make life easier for users&lt;/strong&gt; so that they don'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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finally, development time is money&lt;/strong&gt;, so if the client's budget is limited, you have to take it into consideration and offer the best value solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  WHAT ARE THE OPTIONS?
&lt;/h2&gt;

&lt;p&gt;Once you start researching potential solutions, you will realize that &lt;strong&gt;you face a dilemma regarding where the big part of biometrics implementation should take place&lt;/strong&gt;. On the backend, the mobile app or actually somewhere in between?&lt;/p&gt;

&lt;h3&gt;
  
  
  1. MOBILE APP IMPLEMENTATION
&lt;/h3&gt;

&lt;p&gt;This approach is a very pragmatic and fast solution especially in cases &lt;strong&gt;when one does not want to rely on your backend counterpart's implementation&lt;/strong&gt;. There can be many reasons: a limited client's budget, time sensitivity when the backend team is focused on another feature or just no need for a complex solution.&lt;/p&gt;

&lt;p&gt;How does it work? Upon the user's first signup or login, we can &lt;strong&gt;store the user's credentials securely on the mobile device&lt;/strong&gt; (iOS Keychain or Android Keystore). To achieve this, we can utilize, for example, the &lt;a href="https://github.com/oblador/react-native-keychain" rel="noopener noreferrer"&gt;react-native-keychain&lt;/a&gt; library that allows us to hide the sensitive data behind biometrics authentication. Once a user's authenticated session expires, we offer a biometrics challenge and, if successfully passed, we retrieve the stored credentials to initiate a login API call.&lt;/p&gt;

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

&lt;p&gt;This solution is not very sophisticated and therefore has some drawbacks. For example, if the mobile application complements a website where the user can &lt;strong&gt;change or reset his/her password&lt;/strong&gt;, the next mobile login request after biometrics authentication will fail and we will need to ask for the user's credentials again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security might also be quite a concern&lt;/strong&gt; because the user's credentials are stored on a mobile device, which is not considered best practice. The &lt;a href="https://github.com/oblador/react-native-keychain" rel="noopener noreferrer"&gt;react-native-keychain library warns&lt;/a&gt; that the data could even be easily decrypted on devices running older than the Android 6.0 operating system. &lt;strong&gt;Use this option for fast implementation and simple flows where security is not the highest priority&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. BACKEND IMPLEMENTATION
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Having backend implementation allows us to utilize an extra layer of security&lt;/strong&gt;, which is desirable for applications that want to go the extra mile in securing users' data.&lt;/p&gt;

&lt;p&gt;The solution that offers itself is utilizing &lt;strong&gt;an RSA algorithm by creating a public/private key pair&lt;/strong&gt; 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.&lt;/p&gt;

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

&lt;p&gt;Source: &lt;a href="https://android-developers.googleblog.com/2015/10/new-in-android-samples-authenticating.html" rel="noopener noreferrer"&gt;android-developers.googleblog.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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. &lt;strong&gt;Remember that the private key should not travel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This way, we shift a big portion of work to the backend, &lt;strong&gt;which can lead to much longer delivery time and cost for the client&lt;/strong&gt;. On the other hand, &lt;strong&gt;this approach can be reused&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;In React Native, this solution is readily available with the &lt;a href="https://github.com/SelfLender/react-native-biometrics" rel="noopener noreferrer"&gt;react-native-biometrics&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To offer the users the best experience, we can implement our approach with two separate libraries:&lt;/strong&gt; &lt;a href="https://docs.expo.dev/versions/latest/sdk/local-authentication/" rel="noopener noreferrer"&gt;expo-local-authentication&lt;/a&gt; for the biometrics part and &lt;a href="https://www.npmjs.com/package/react-native-rsa-native" rel="noopener noreferrer"&gt;react-native-rsa-native&lt;/a&gt; for the RSA algorithm. &lt;strong&gt;Use this option for a more security-focused approach when backend resources are available and the deadline is not a week.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. COMBINED IMPLEMENTATION
&lt;/h3&gt;

&lt;p&gt;If our application utilizes refresh tokens, we can smartly combine the two previous options together. Upon signup or login, &lt;strong&gt;we can store a new refresh token securely on the device&lt;/strong&gt; using the &lt;a href="https://github.com/oblador/react-native-keychain" rel="noopener noreferrer"&gt;react-native-keychain&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;The big security advantage compared to the first solution is that &lt;strong&gt;we don't have to keep the sensitive login credentials stored on the device&lt;/strong&gt;. Also, backend verification of the refresh token provides certain security aspects we implemented with the second solution.&lt;/p&gt;

&lt;p&gt;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's session.&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>security</category>
      <category>biometrics</category>
    </item>
    <item>
      <title>A Step By Step Guide To Writing Your First Expo Config Plugin</title>
      <dc:creator>Áron Berezkin</dc:creator>
      <pubDate>Thu, 16 Dec 2021 21:01:25 +0000</pubDate>
      <link>https://dev.to/aronberezkin/a-step-by-step-guide-to-writing-your-first-expo-config-plugin-fj</link>
      <guid>https://dev.to/aronberezkin/a-step-by-step-guide-to-writing-your-first-expo-config-plugin-fj</guid>
      <description>&lt;p&gt;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 &lt;a href="https://docs.expo.dev/guides/config-plugins/"&gt;config plugins&lt;/a&gt; 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's status bar translucent behavior to allow our splash screen reach all device edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  INITIAL SETUP
&lt;/h2&gt;

&lt;p&gt;To initiate our project you can simply clone &lt;a href="https://github.com/AronBe/article-first-config-plugin"&gt;this repository&lt;/a&gt; that has all demonstrative assets included. Or you can start yourself by running expo-cli:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo init first-config-plugin &lt;span class="nt"&gt;-t&lt;/span&gt; expo-template-blank-typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add &lt;a href="https://docs.expo.dev/versions/latest/sdk/splash-screen/"&gt;expo-splash-screen&lt;/a&gt; as your dependency..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo &lt;span class="nb"&gt;install &lt;/span&gt;expo-splash-screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;..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.&lt;/p&gt;

&lt;h2&gt;
  
  
  THE ISSUE
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;translucent&lt;/code&gt; so that image can stretch under it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatusBar&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt; &lt;span class="na"&gt;translucent&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"transparent"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VxNPQcRZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mrf5cam5e299me97kng.gif" class="article-body-image-wrapper"&gt;&lt;img alt="non translucent status bar demo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--VxNPQcRZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mrf5cam5e299me97kng.gif" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;
Click for better resolution



&lt;p&gt;Luckily Expo allows us to configure the Android status bar through &lt;a href="https://docs.expo.dev/versions/latest/config/app/#androidstatusbar"&gt;app.json&lt;/a&gt; which will set the default behavior before the app mounts. Lets try to replicate our settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"androidStatusBar"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#00000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"barStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dark-content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"translucent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ssuC7Mwk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0at5teccqdr7lsl2xon.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ssuC7Mwk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0at5teccqdr7lsl2xon.gif" alt="translucent status bar demo" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;
Click for better resolution



&lt;p&gt;We need to investigate what is going on. By running &lt;code&gt;expo run:android&lt;/code&gt; or &lt;code&gt;expo prebuild -p android&lt;/code&gt; we can generate the Android folder with its configurations. If you don'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 (&lt;code&gt;git add -A&lt;/code&gt;), remove &lt;code&gt;translucent: true&lt;/code&gt; from app.json, and run &lt;code&gt;expo prebuild -p android&lt;/code&gt; to generate native files again.&lt;/p&gt;

&lt;p&gt;By removing the translucent property you should see following unstaged changes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;android/app/src/main/res/values/strings.xml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;- &lt;span class="nt"&gt;&amp;lt;string&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"expo_splash_screen_status_bar_translucent"&lt;/span&gt; &lt;span class="na"&gt;translatable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
+ &lt;span class="nt"&gt;&amp;lt;string&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"expo_splash_screen_status_bar_translucent"&lt;/span&gt; &lt;span class="na"&gt;translatable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;android/app/src/main/res/values/styles.xml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;- &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"android:windowTranslucentStatus"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This already looks promising as the &lt;code&gt;expo_splash_screen_status_bar_translucent&lt;/code&gt; custom Expo property sounds exactly like something we are trying to influence and being previously &lt;code&gt;true&lt;/code&gt; we saw the status bar was really translucent during the splash screen. We also notice that &lt;code&gt;android:windowTranslucentStatus&lt;/code&gt; was set to &lt;code&gt;true&lt;/code&gt; 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't have one without the other to reach the behavior you wanted and the only option was to raise it in Expo &lt;a href="https://github.com/expo/expo/issues/11604#issuecomment-964953312"&gt;issues&lt;/a&gt;. But now thanks to Expo config plugins you can take the solution in your hands.&lt;/p&gt;

&lt;h2&gt;
  
  
  THE SOLUTION
&lt;/h2&gt;

&lt;p&gt;The solution is to make &lt;code&gt;expo_splash_screen_status_bar_translucent&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt; while keeping &lt;code&gt;android:windowTranslucentStatus&lt;/code&gt; as &lt;code&gt;false&lt;/code&gt; - which is the default therefore lets change only the Expo property. With &lt;code&gt;expo run:android&lt;/code&gt; 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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This means any native changes through plugins will be reflected in Expo development environment only using &lt;a href="https://docs.expo.dev/development/getting-started/"&gt;expo-dev-client&lt;/a&gt; - our custom Expo Go.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;@expo/config-plugins&lt;/code&gt; package is already part of Expo, so we don'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.&lt;/p&gt;

&lt;p&gt;Lets create our initial plugin file &lt;code&gt;withAndroidSplashScreen.ts&lt;/code&gt; in the root folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConfigPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@expo/config-plugins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withStringsXml&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@expo/config-plugins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withAndroidSplashScreen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;withStringsXml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;modConfig&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withAndroidSplashScreen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And start compiling it into javascript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn tsc withAndroidSplashScreen.ts &lt;span class="nt"&gt;--watch&lt;/span&gt; &lt;span class="nt"&gt;--skipLibCheck&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, import resulting &lt;code&gt;withAndroidSplashScreen.js&lt;/code&gt; file into app.json &lt;code&gt;plugins&lt;/code&gt; property for Expo to process it on a next build. Our changes look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...otherProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"androidStatusBar"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#00000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"barStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dark-content"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./withAndroidSplashScreen.js"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can run &lt;code&gt;expo prebuild -p android&lt;/code&gt; to see effects of your plugin. Obviously, if you inspect our &lt;code&gt;withAndroidSplashScreen&lt;/code&gt; code it is not changing anything yet. It just returns whatever it receives. Our plugin is a simple function.&lt;/p&gt;

&lt;p&gt;Initially our plugin receives &lt;code&gt;expoConfig&lt;/code&gt; which is basically content of &lt;code&gt;app.json&lt;/code&gt; and this object is passed to the &lt;code&gt;withStringXml&lt;/code&gt; mod. This particular mod (modifier) from Expo enables us to read contents of &lt;strong&gt;android/app/src/main/res/values/strings.xml&lt;/strong&gt; and change them based on what config we return (all available mods can be found &lt;a href="https://docs.expo.dev/guides/config-plugins/#mod-plugins"&gt;here&lt;/a&gt;). For each mod its content can be read from &lt;code&gt;modConfig.modResults&lt;/code&gt; - you can actually use &lt;code&gt;console.log(JSON.stringify(config.modResults, null, 2));&lt;/code&gt; to inspect the values during the &lt;code&gt;prebuild&lt;/code&gt; command. To apply our desired changes we need to modify &lt;code&gt;modResults&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConfigPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@expo/config-plugins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AndroidConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;withStringsXml&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@expo/config-plugins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withAndroidSplashScreen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;withStringsXml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expoConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;modConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AndroidConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setStringItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expo_splash_screen_status_bar_translucent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;translatable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;false&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="nx"&gt;modConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modResults&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;modConfig&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withAndroidSplashScreen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, we assign to &lt;code&gt;modResults&lt;/code&gt; what is returned from AndroidConfig helper method &lt;code&gt;setStringItem&lt;/code&gt; which accepts the value we want to add and then remaining file strings already existing. Inspecting type of &lt;code&gt;setStringItem&lt;/code&gt; and typescript in general should help you fill all needed properties correctly. After running &lt;code&gt;prebuild&lt;/code&gt; we should see a new configuration string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;+ &lt;span class="nt"&gt;&amp;lt;string&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"expo_splash_screen_status_bar_translucent"&lt;/span&gt; &lt;span class="na"&gt;translatable=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have our desired splash screen behavior with a translucent status bar already from the app start and without the ugly overlay.&lt;/p&gt;

&lt;h2&gt;
  
  
  SUMMARY
&lt;/h2&gt;

&lt;p&gt;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 &lt;a href="https://github.com/AronBe/article-first-config-plugin/tree/solution"&gt;this branch&lt;/a&gt;. 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 &lt;code&gt;prebuild&lt;/code&gt; 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.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>splashscreen</category>
      <category>react</category>
    </item>
    <item>
      <title>What I Learned as a Web Dev on My First React Native Project</title>
      <dc:creator>Áron Berezkin</dc:creator>
      <pubDate>Wed, 15 Dec 2021 19:37:37 +0000</pubDate>
      <link>https://dev.to/aronberezkin/what-i-learned-as-a-web-dev-on-my-first-react-native-project-1gk</link>
      <guid>https://dev.to/aronberezkin/what-i-learned-as-a-web-dev-on-my-first-react-native-project-1gk</guid>
      <description>&lt;p&gt;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't a key factor—and I got great support from my colleagues. But let's face it: With older projects, you mostly deal with bugs, optimizations and continued refactoring, plus some features here and there.&lt;/p&gt;

&lt;p&gt;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 &lt;strong&gt;greater perspective&lt;/strong&gt;; that'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.&lt;/p&gt;

&lt;p&gt;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 &lt;strong&gt;React Native (RN) project&lt;/strong&gt;. Just like that, together with my senior colleague, I started building a new &lt;strong&gt;mobile&lt;/strong&gt; app for iOS and Android using my &lt;strong&gt;web development skills&lt;/strong&gt;. Meaning that my previous article should be renamed to &lt;a href="https://www.strv.com/blog/how-i-left-a-financial-markets-career-for-web-development-insidestrv-engineering"&gt;How I Left a Financial Markets Career for &lt;del&gt;Web&lt;/del&gt; Frontend Development&lt;/a&gt;. And, as in the previous article, this experience has come with plenty of lessons worth sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  GETTING STARTED
&lt;/h2&gt;

&lt;p&gt;While the React Native coding environment feels quite familiar to a React developer, &lt;strong&gt;you actually lack the knowledge of what you are able to build with your skills.&lt;/strong&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning
&lt;/h3&gt;

&lt;p&gt;Perpetually finding myself in somewhat of a "code newbie" mindset, I know that there are certain gaps in my coding skills that I need to fill.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://www.youtube.com/watch?v=0-S5a0eXPoc"&gt;course&lt;/a&gt; (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'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.&lt;/p&gt;

&lt;p&gt;Another great tutor, The Net Ninja, has a free &lt;a href="https://www.youtube.com/watch?v=ur6I5m2nTvk&amp;amp;list=PL4cUxeGkcC9ixPU-QkScoRBVxtPPzVjrQ"&gt;course&lt;/a&gt; also worth checking out. And finally, I've discovered William Candillon, who is a big guru in the React Native community especially thanks to his "&lt;a href="https://www.youtube.com/watch?v=-PEaIQb09oQ&amp;amp;list=PLkOyNuxGl9jxB_ARphTDoOWf5AE1J-x1r&amp;amp;index=10"&gt;Can it be done in React Native?&lt;/a&gt;" YouTube series. While William is mostly focused on animations, around that time he also started a series called &lt;a href="https://www.youtube.com/watch?v=MqRnpUC4czs&amp;amp;list=PLkOyNuxGl9jyhndcnbFcgNM81fZak7Rbw&amp;amp;index=25"&gt;"React Native Fashion"&lt;/a&gt;, 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!&lt;/p&gt;

&lt;h3&gt;
  
  
  Expo vs. React Native CLI?
&lt;/h3&gt;

&lt;p&gt;You will find that almost all tutorials, be it the ones from YouTube or Medium, will use &lt;a href="https://docs.expo.io/"&gt;Expo&lt;/a&gt;, a framework and set of tools for building React Native applications. Its "managed" 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 &lt;strong&gt;a great choice for a tutorial or an MVP, but is it good for a professionally built app&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;For now, it usually isn't! Expo does not allow you to touch native Android and iOS modules and, in general, you are &lt;strong&gt;locked to their environment&lt;/strong&gt; — which is very powerful, but the situation is still not ideal. If you'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 &lt;strong&gt;React Native CLI to build apps so that we can provide the best value for our clients' money.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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. &lt;strong&gt;Avoiding difficult things may just create internal anxiety that will surface later.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  THE DEVELOPMENT EXPERIENCE
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does It Work on Both Android and iOS?
&lt;/h3&gt;

&lt;p&gt;As a web dev, you check how your app behaves across various internet browsers. In mobile development, you check &lt;strong&gt;if things are working in the same way on both Android and iOS.&lt;/strong&gt; 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'll have to utilize preset &lt;a href="https://reactnative.dev/docs/view-style-props#elevation"&gt;elevation&lt;/a&gt; properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does It Look on My Old Nexus Versus Iphone 12?
&lt;/h3&gt;

&lt;p&gt;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. &lt;strong&gt;This can easily lead to misaligned design.&lt;/strong&gt; If your simulator is big enough and fits all things on one screen, it may require a &lt;a href="https://reactnative.dev/docs/using-a-scrollview"&gt;ScrollView&lt;/a&gt; component on a smaller device to allow users to reach all the offscreen content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging
&lt;/h3&gt;

&lt;p&gt;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're used to. Tools such as &lt;a href="https://github.com/jhen0409/react-native-debugger"&gt;React Native Debugger&lt;/a&gt; are also quite popular, but they require turning on the '&lt;strong&gt;Remote debugging&lt;/strong&gt;' mode on your simulator, which I found sometimes interferes with the app and throws weird errors.&lt;/p&gt;

&lt;p&gt;With React Native version 0.62 comes &lt;a href="https://fbflipper.com/docs/features/react-native/"&gt;Flipper&lt;/a&gt;, Facebook's own debugging tool &lt;strong&gt;included as a default&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://www.youtube.com/watch?v=wVJxb36wjjA"&gt;talk&lt;/a&gt; on Xcode.&lt;/p&gt;

&lt;p&gt;To be honest, &lt;strong&gt;debugging errors will take a long time to get used to.&lt;/strong&gt; For a novice, it is not always apparent where the error is coming from. And, more importantly, it'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's how you will save time later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fast Refresh
&lt;/h3&gt;

&lt;p&gt;When things are going quite smoothly, something I really enjoy is &lt;a href="https://reactnative.dev/docs/fast-refresh"&gt;Fast Refresh&lt;/a&gt;, 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  CODING TIPS
&lt;/h2&gt;

&lt;p&gt;There'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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling
&lt;/h3&gt;

&lt;p&gt;All your components are &lt;code&gt;display: flex&lt;/code&gt; and &lt;code&gt;flexDirection: column&lt;/code&gt; as default, so forget grids and blocks and brush up on your flexbox skills. You will often be tempted to use &lt;code&gt;flex: 1&lt;/code&gt; to make your container fill the whole screen or all available space, which is perfectly fine—but remember that these don't have to play nicely if your component has any animation elements and the device has to recalculate the space. Similarly, another default is &lt;code&gt;position: relative&lt;/code&gt;, meaning your absolute elements are positioned relative to their parent.&lt;/p&gt;

&lt;p&gt;Forget CSS pseudo-elements and selectors; in React Native, &lt;strong&gt;we inline the styles.&lt;/strong&gt; 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, &lt;a href="https://github.com/Shopify/restyle"&gt;Restyle&lt;/a&gt; from Shopify is gaining popularity.&lt;/p&gt;

&lt;p&gt;You can also choose from several &lt;strong&gt;UI kits&lt;/strong&gt; to get started on your hobby project. Popular ones are, for example, &lt;a href="https://callstack.github.io/react-native-paper/"&gt;React Native Paper&lt;/a&gt; and &lt;a href="https://akveo.github.io/react-native-ui-kitten/"&gt;UI Kitten&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By the way, remember that you don'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 &lt;strong&gt;accessibility props&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Images
&lt;/h3&gt;

&lt;p&gt;You cannot use .svg files as a source for RN's Image component. You will probably end up using pngs, ideally 3x the size to account for iPhones' scale factor—so don't forget to compress it! If you want to use svgs, use &lt;a href="https://github.com/react-native-svg/react-native-svg"&gt;React-Native-SVG&lt;/a&gt; library and &lt;a href="https://react-svgr.com/playground/"&gt;SVGR&lt;/a&gt; playground for quick conversion to an RN component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Animations
&lt;/h3&gt;

&lt;p&gt;You can use the built-in &lt;a href="https://reactnative.dev/docs/animations"&gt;Animated&lt;/a&gt; API, which performs well especially when using &lt;code&gt;useNativeDriver: true&lt;/code&gt; prop. However, you get the best performance with the &lt;a href="https://github.com/software-mansion/react-native-reanimated"&gt;React-Native-Reanimated&lt;/a&gt; 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 &lt;a href="https://airbnb.design/lottie/"&gt;Lottie&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Libraries
&lt;/h3&gt;

&lt;p&gt;In general, there are actually many built-in &lt;a href="https://reactnative.dev/docs/components-and-apis"&gt;components &lt;/a&gt;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 &lt;a href="https://github.com/react-native-community"&gt;React Native Community&lt;/a&gt; repo for maintenance.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://developer.android.com/studio/build/multidex"&gt;Multidex&lt;/a&gt;. Another error may come if you enable &lt;a href="https://reactnative.dev/docs/hermes"&gt;Hermes&lt;/a&gt;, an optimized Javascript engine for running Android apps and, soon, also &lt;a href="https://github.com/react-native-community/releases/issues/214"&gt;iOS&lt;/a&gt;. While some libraries—like the above-mentioned Reanimated—require it, others are not yet compatible with it (Realm - see below).&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard Avoiding View
&lt;/h3&gt;

&lt;p&gt;No comment. If you've worked with React Native, you get this. It is a topic one would rather skip. When you work with text inputs, &lt;strong&gt;you have to account for the keyboard sliding from the bottom&lt;/strong&gt;, hence we utilize the &lt;a href="https://reactnative.dev/docs/keyboardavoidingview"&gt;Keyboard Avoiding View&lt;/a&gt; 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's &lt;a href="https://developer.android.com/training/keyboard-input/visibility"&gt;windowSoftInputMode&lt;/a&gt; at some point to get the best experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Landscape Mode
&lt;/h3&gt;

&lt;p&gt;Another unpleasant thing you might face is optimizing for the landscape mode. For most apps, it is common practice to just disable it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigation
&lt;/h3&gt;

&lt;p&gt;To navigate between screens, you will probably end up using the very popular &lt;a href="https://reactnavigation.org/"&gt;React Navigation&lt;/a&gt; library. There is a great, purely native alternative, &lt;a href="https://github.com/wix/react-native-navigation"&gt;React Native Navigation&lt;/a&gt; (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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storing Data
&lt;/h3&gt;

&lt;p&gt;The Redux library is quite a common choice thanks to its broad ecosystem. Luckily, there is now a very useful &lt;a href="https://redux-toolkit.js.org/"&gt;Redux Toolkit&lt;/a&gt; that mitigates the amount of boilerplate you have to usually write. &lt;a href="https://github.com/rtk-incubator/rtk-query"&gt;RTK Query&lt;/a&gt; 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 &lt;a href="https://github.com/rt2zz/redux-persist"&gt;libraries&lt;/a&gt; that persist and rehydrate the global state for users when they relaunch the app.&lt;/p&gt;

&lt;p&gt;To persist data on the device, it is common to use &lt;a href="https://github.com/react-native-async-storage/async-storage"&gt;AsyncStorage&lt;/a&gt;, which is an asynchronous alternative to web's LocalStorage. Another interesting option (though a bit more complex) is to use the &lt;a href="https://realm.io/docs/javascript/latest/"&gt;Realm&lt;/a&gt; database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Mobile Development Considerations
&lt;/h3&gt;

&lt;p&gt;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 &lt;a href="https://github.com/zoontek/react-native-permissions"&gt;React Native Permissions&lt;/a&gt; library to offer a consistent experience across platforms.&lt;/p&gt;

&lt;p&gt;Further, mobile devices can lose connectivity easily; for that, you can count on the &lt;a href="https://github.com/react-native-netinfo/react-native-netinfo"&gt;NetInfo&lt;/a&gt; library to offer a user experience while offline. Finally, notifications are an essential part of mobile apps and &lt;a href="https://rnfirebase.io/"&gt;Firebase&lt;/a&gt; offers great React Native integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  FINAL WORDS
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://www.aronberezkin.com/posts/what-i-learned-as-a-web-dev-on-my-first-react-native-project"&gt;aronberezkin.com&lt;/a&gt; and &lt;a href="https://www.strv.com/blog/what-i-learned-as-a-web-dev-on-my-first-react-native-project-engineering"&gt;strv.com&lt;/a&gt; on February 18, 2021. &lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>mobile</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Left a Financial Markets Career for Web Development</title>
      <dc:creator>Áron Berezkin</dc:creator>
      <pubDate>Wed, 15 Dec 2021 19:17:34 +0000</pubDate>
      <link>https://dev.to/aronberezkin/how-i-left-a-financial-markets-career-for-web-development-34h8</link>
      <guid>https://dev.to/aronberezkin/how-i-left-a-financial-markets-career-for-web-development-34h8</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I studied finance &amp;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 &lt;a href="https://www.strv.com/"&gt;STRV&lt;/a&gt; — starting my journey as a web developer.&lt;/p&gt;

&lt;p&gt;As you might guess, the path to get here wasn't clearcut. The biggest roadblock for a person changing careers is the psychological battle. Your brain can easily calculate what you're leaving behind (10 years in finance), but can't really determine what you might gain. Let's go over what to ask yourself when making this big life decision, and how to move forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  DECIDING IF IT'S THE RIGHT MOVE
&lt;/h2&gt;

&lt;p&gt;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's also gone through a career change. If you don't personally know anyone that fits the bill, you can easily find someone at a local development meetup (use the &lt;a href="https://www.meetup.com/"&gt;Meetup&lt;/a&gt; app or &lt;a href="https://www.facebook.com/events/"&gt;Facebook events&lt;/a&gt;). You can also read about building a web development career at &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt; or &lt;a href="https://medium.com/"&gt;Medium&lt;/a&gt;, watch relevant Youtube videos or listen to a podcast. I did all of that and found everything equally helpful. &lt;strong&gt;Remember: You're entering a very broad and fast-moving space, so one developer alone cannot provide all the necessary info.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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's been in the industry for years, those newer to the job find this exciting. This actually gives newbies a great advantage — &lt;strong&gt;companies need fresh, flexible minds that are enthusiastic and willing to learn a specific stack of technologies used&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As for having joined STRV, I'm thrilled to have the opportunity to determine my own hours and, even more than that, it's incredible to have smart colleagues around, all of whom help me develop my coding skills and provide guidance when trying new technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  READY TO LEARN?
&lt;/h2&gt;

&lt;p&gt;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'd recommend starting with the first category (as though it's the first step) and going from there—or choosing and combining what works for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Platforms
&lt;/h3&gt;

&lt;p&gt;If you'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 &lt;a href="https://www.codecademy.com/"&gt;Codecademy&lt;/a&gt;, &lt;a href="https://www.sololearn.com/"&gt;Sololearn&lt;/a&gt; or freeCodecamp basic courses. They are great because &lt;strong&gt;you don't have to install or set anything up&lt;/strong&gt;, which can be a demotivating headache for a beginner. Some of them have a mobile app, too.&lt;/p&gt;

&lt;p&gt;The apps teach users that writing code has to be precise. For example, it'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 'login' or 'logout' 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Video Tutorials
&lt;/h3&gt;

&lt;p&gt;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. &lt;a href="https://www.udemy.com/"&gt;Udemy&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When searching for videos, finding updated content is crucial given that the technologies advance very quickly.&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;Once you'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 &lt;a href="http://youtube.com/channel/UCJZv4d5rbIKd4QHMPkcABCw"&gt;Kevin Powell&lt;/a&gt; (html/css), &lt;a href="https://www.youtube.com/channel/UCW5YeuERMmlnqo4oq8vwUpg"&gt;The Net Ninja&lt;/a&gt; (frontend) and &lt;a href="https://www.youtube.com/channel/UC29ju8bIPH5as8OGnQzwJyA"&gt;Traversy Media&lt;/a&gt; (various tutorials).&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivation, Inspiration, Clarity
&lt;/h3&gt;

&lt;p&gt;Following a lengthy tutorial, you often get to a point when it's useful to step back from coding and consolidate what you've learned. Listening to podcasts such as &lt;a href="https://www.codenewbie.org/"&gt;CodeNewbie&lt;/a&gt; and &lt;a href="https://syntax.fm/"&gt;Syntax&lt;/a&gt; or watching YouTube videos like &lt;a href="https://www.youtube.com/watch?v=0pThnRneDjw"&gt;Web Development in 2020&lt;/a&gt; can complement the learning process, help you keep up with the industry's new trends and guide you in what to learn next.&lt;/p&gt;

&lt;p&gt;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're struggling to answer, &lt;strong&gt;focus on keeping your motivations high by remembering where you're headed: building something real and valuable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://twitter.com/search?q=%23100DaysOfCode&amp;amp;src=hashtag_click"&gt;#100DaysOfCode&lt;/a&gt; challenge to join a great community of upcoming programmers, who will support you whenever needed.&lt;/p&gt;

&lt;p&gt;Content can feel repetitive after some time, especially while you haven't moved on to advanced topics yet. But personally, I loved this part of the learning process because it's — unlike when you'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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meetups, Bootcamps, Academies
&lt;/h3&gt;

&lt;p&gt;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're a newbie, but give it a few months. Keep listening and learning. You'll gain a lot more clarity about standards and new trends in development. I once went to a &lt;a href="https://jamstack.org/"&gt;Jamstack&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;Bootcamps are also a popular way to speed up the learning process, but they aren't for everyone. &lt;strong&gt;It depends on whether you prefer learning at your own pace or the pace set by a tutor&lt;/strong&gt;. 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As part of their hiring process, some development companies set up academies&lt;/strong&gt; where they invite both developers and non-developers to attend a series of workshops. It'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 &lt;a href="https://github.com/strvcom/react-nights-2019"&gt;STRV React Nights&lt;/a&gt; in 2019 definitely played an important role in eventually getting hired.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building stuff
&lt;/h3&gt;

&lt;p&gt;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's nothing wrong with turning to your peers or sources for inspiration. Have a look back at the tutorials you've gone through or check out STRV's open source &lt;a href="https://github.com/strvcom"&gt;templates&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A big question during this time is: What do you actually build? If you come up with an idea, do it. &lt;strong&gt;Starting a project will be your biggest motivation&lt;/strong&gt;. And if you're low on ideas, a good tactic is to start replicating designs of other websites, even popular ones like Twitter. &lt;a href="https://developers.google.com/web/tools/chrome-devtools/"&gt;Google Developer Tools&lt;/a&gt; can help to guide you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good way to give purpose to your project is by adding it to your portfolio&lt;/strong&gt;. You probably don'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'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 ¯\_(ツ)_/¯.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be kind to yourself during this stage. Becoming confident in your coding skills takes time.&lt;/strong&gt; Nobody expects you to know everything and write code on par with senior developers. Embrace being a newbie.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mentoring
&lt;/h3&gt;

&lt;p&gt;Having a mentor is not a requirement when becoming a developer. For most of my career-change journey, I'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.&lt;/p&gt;

&lt;p&gt;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. &lt;strong&gt;You might be surprised, but most developers are more than happy to offer you their help&lt;/strong&gt; — for them, it'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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teaching
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The ultimate way to solidify your knowledge is to teach someone what you know.&lt;/strong&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  ON A PERSONAL NOTE
&lt;/h2&gt;

&lt;p&gt;Learning coding can be frustrating at times. The biggest lessons often come from failing and fixing your mistakes, meaning you'll sometimes feel like you've hit a wall. And when trying to make a career shift, hitting a wall can be especially demotivating. You may question whether it's even worth it. Whether it'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!&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://www.aronberezkin.com/posts/how-i-left-a-financial-markets-career-for-web-development"&gt;aronberezkin.com&lt;/a&gt; and &lt;a href="https://www.strv.com/blog/what-i-learned-as-a-web-dev-on-my-first-react-native-project-engineering"&gt;strv.com&lt;/a&gt; on February 25, 2020.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>codenewbie</category>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
