<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Reactnative blogs, learn and share growth, tech-blogs, Agrit Tiwari]]></title><description><![CDATA[Sharing the learnings of tech developer journey. Exploring the world of web and Mobile, the trends of complex, highly interactive and heavy frontend designs and systems, cross platform development.]]></description><link>https://tech-blog.agrittiwari.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1622024822921/eH1-T83gV.png</url><title>Reactnative blogs, learn and share growth, tech-blogs, Agrit Tiwari</title><link>https://tech-blog.agrittiwari.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Apr 2026 01:20:54 GMT</lastBuildDate><atom:link href="https://tech-blog.agrittiwari.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How we built multi-platform app at Wishup with Expo]]></title><description><![CDATA[Wishup is a multi-platform app that lets entrepreneurs discover right remote assistants, from a pool of vetted, trained and top 0.0001% talents and manage work seamlessly on day to day chores.

Extending UI
Wherever possible extend the UI, margins pa...]]></description><link>https://tech-blog.agrittiwari.com/how-we-built-multi-platform-app-at-wishup-with-expo</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/how-we-built-multi-platform-app-at-wishup-with-expo</guid><category><![CDATA[Expo]]></category><category><![CDATA[expo-router]]></category><category><![CDATA[React Native]]></category><category><![CDATA[react-native-web]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Wed, 14 May 2025 04:26:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747196716468/4678d074-f83a-4aaa-9ab2-2d6cd02b0818.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://www.wishup.co/virtual-assistant-company?ref=y2u3zjg">Wishup</a> is a multi-platform app that lets entrepreneurs discover right remote assistants, from a pool of vetted, trained and top 0.0001% talents and manage work seamlessly on day to day chores.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747194940721/71ba68c4-5edf-4e11-88ab-607c4556e2a9.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-extending-ui">Extending UI</h3>
<p>Wherever possible extend the UI, margins paddings to exisitng components with responsive code. We used <a target="_blank" href="http://tamagui.dev">Tamagui</a> to build our app and it was super easy to extend the UI components to web, just by adding sm, lg, gt props to pass in styles responsive to various screen sizes.</p>
<h3 id="heading-used-platform-extensions">Used Platform extensions</h3>
<p>For platform specific resolution of certain components and behavior. It is best to colocate the files, give same names and import the code, component and metro will resolve the respective platform files. Layout and access varies distinctly from mobile to web, so writing platform specific module is a great practice we adopt. Creating filename.web.ts, wherever there is a web specific implementation needed for that feature.</p>
<h3 id="heading-push-notification-and-web-push-subscription">Push Notification and Web Push Subscription</h3>
<p>Building Push notification feature is straight-forward with <a target="_blank" href="https://docs.expo.dev/push-notifications/push-notifications-setup/">Expo push notifications</a>, but to add support for a push notifications on web, that needs a service worker setup to create subscription for that browser. I have created this <a target="_blank" href="https://gist.github.com/agrittiwari/bad34f6cbf2bb65b2fd99b05eb2a3d93">gist</a> to refer and implement the push notifications on expo-web.</p>
<p>The problem with push notifications on web is it can only be implemented in a service worker.</p>
<blockquote>
<p>The <a target="_blank" href="https://developer.mozilla.org/docs/Web/API/IndexedDB_API">IndexedDB</a> and <a target="_blank" href="https://developer.mozilla.org/docs/Web/API/CacheStorage">Cache Storage</a> APIs are accessible in service workers. However, <a target="_blank" href="https://developer.mozilla.org/docs/Web/API/Window/localStorage">Local Storage</a> and <a target="_blank" href="https://developer.mozilla.org/docs/Web/API/Window/sessionStorage">Session Storage</a> are not.</p>
</blockquote>
<p>So, we wrote every function mapping the utility to our persistent storage solution of mobile, i.e., MMKV storage, which use localstorage on web.</p>
<p>LocalStorage is also not reactive and to handle the variables that need to run callbacks and reactivity, added all the hooks to refer the values and user data in indexedDB.</p>
<h3 id="heading-react-navigation-v7-upgrade">React Navigation v7 upgrade</h3>
<p>To build the sidebar on web, and chat interface as a common component across all tabs, we upgraded the app to v7 of react navigation making use of `tabBarPosition` to render sidebar for web platform, and end up passing the custom UI for sidebar.<br />We make use of layout prop of the navigators and screen to render shared components across the navigators and screens. It made features like our Chat very easy to implement as most of the heavy lifting is done by the library.<br />Later, we wrote the aliases against every navigator and screens, for better url structures, while implementing universal linking and deep links in the hybrid app.</p>
<p>Common workarounds</p>
<p>From writing platform based React context for auth, we use Auth0, to writing conditonal Provider wrappers.<br />Defining and blocking the resolution of certain components that simply does not work on web in Metro and ignoring certain parts of code for one platform and adding extra code for another. Expo 52, tree shakes the codebase and optimising the build anyways. Using Atlas is a great practice to pick and kill unused packages.</p>
<h3 id="heading-deployment">Deployment</h3>
<p>Deployment configuration installs <code>serve</code>, copies the app’s source code, builds the app for the web, and sets up a service worker. It exposes port 8081 and serves the app from the <code>/dist</code> folder on that port.<br />We setup a dockerfile to host the frontend for our app on EC2, It is working alright for now. If something occurs, Expo community is always ready to help.</p>
<h3 id="heading-backend">Backend</h3>
<p>While building the new clients with expo-web we used the same legacy structured Postgres DB and wrote the type APIs over it.<br />Our backend stack is apollo server, with Graphql APIs. We are using prisma to write typed queries, mutations and resolvers and managing our database schema effortlessly. Some AI powered features and server driven UI configurations for certain apps. Usage of Graphql-shield to manage admin roles on the app. It is a great product catering 4 types of user with varying accesses, namely, Clients, VAs, Admin roles and Client’s team members.</p>
<hr />
<p>With this, I am really looking forward to learn more about the rich apps built with expo-web. please hit me up with your implementations at <a target="_blank" href="https://www.x.com/agrit_tiwari">X</a></p>
<p>Thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Supabase Auth: The Ultimate Authentication Solution for Cross-Platform Apps using React  Native]]></title><description><![CDATA[After facing the limitation for an auth package web support, I was looking for auth solutions to have a platform based smooth authentication experience. So the major authentication methods I wanted in the app I was building was,

email+ password

app...]]></description><link>https://tech-blog.agrittiwari.com/supabase-auth-the-ultimate-authentication-solution-for-cross-platform-apps-using-react-native</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/supabase-auth-the-ultimate-authentication-solution-for-cross-platform-apps-using-react-native</guid><category><![CDATA[supabase]]></category><category><![CDATA[Expo]]></category><category><![CDATA[Cross Platform App Development. ]]></category><category><![CDATA[authentication]]></category><category><![CDATA[authorization]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Fri, 26 Jul 2024 14:23:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722003097774/5eee3966-4afd-4855-8113-b30be66e78da.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After facing the limitation for an auth package web support, I was looking for auth solutions to have a platform based smooth authentication experience. So the major authentication methods I wanted in the app I was building was,</p>
<ul>
<li><p>email+ password</p>
</li>
<li><p>apple sign in (iOS native)</p>
</li>
<li><p>google signin (android native)</p>
</li>
</ul>
<p>I wanted to have <strong><em>all these methods available to me on all the targeted platforms (android, iOS and web) for our react-native app</em></strong>. I knew a lot of auth libraries for web, and a lot of libraries for mobile only, and I've been following Supabase's launch week, for quite a while.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://x.com/supabase/status/1646507824015392768">https://x.com/supabase/status/1646507824015392768</a></div>
<p> </p>
<p>when the decision to move on with web build support for the app came in, I dived right in <code>supabase-auth</code> and ended up with a working product that supported native social logins on respective native platforms and browser based logins on web, for our react native application.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://x.com/agrit_tiwari/status/1816839787556311383">https://x.com/agrit_tiwari/status/1816839787556311383</a></div>
<p> </p>
<p>Supabase auth is more than an auth service, it provides you dashboard to manage users and implement Row Level Security for it's users. Auth hooks are an added feature to implement custom behavior on user creation. Check more here:<br /><a target="_blank" href="https://supabase.com/docs/guides/auth/auth-hooks">https://supabase.com/docs/guides/auth/auth-hooks</a></p>
<hr />
<h3 id="heading-how-to-setup-auth-in-an-expo-app">How to setup auth in an Expo app</h3>
<p>We are using Tamagui(ui lib) in the app, so make sure to install it.<br /><code>yarn add @tamagui</code></p>
<p>Let me just share the code snippets and a walkthrough tutorial of how you can achieve the same set of authentication, which to me sounds ideal.</p>
<p>Install the following packages to setup supabase client, storage and secure store for cross-platform expo app.</p>
<pre><code class="lang-bash">yarn add @supabase/supabase-js expo-crypto expo-secure-store react-native-mmkv
</code></pre>
<p>Create a <code>storage.ts</code> and <code>supabase.ts</code> under <code>/utils</code> folder</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;
<span class="hljs-keyword">import</span> { AppState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'react-native-url-polyfill/auto'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> SessionStorage <span class="hljs-keyword">from</span> <span class="hljs-string">'./storage'</span>;
<span class="hljs-keyword">const</span> supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL;
<span class="hljs-keyword">const</span> supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> supabase = createClient(supabaseUrl, supabaseAnonKey, {
  auth: {
    storage: SessionStorage,
    autoRefreshToken: <span class="hljs-literal">true</span>,
    persistSession: <span class="hljs-literal">true</span>,
    detectSessionInUrl: <span class="hljs-literal">false</span>,
  },
});
<span class="hljs-keyword">export</span> { <span class="hljs-keyword">type</span> AuthError, <span class="hljs-keyword">type</span> Session } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>;

<span class="hljs-comment">/**
 * Tells Supabase to autorefresh the session while the application
 * is in the foreground. (Docs: https://supabase.com/docs/reference/javascript/auth-startautorefresh)
 */</span>
AppState.addEventListener(<span class="hljs-string">'change'</span>, <span class="hljs-function">(<span class="hljs-params">nextAppState</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (nextAppState === <span class="hljs-string">'active'</span>) {
    supabase.auth.startAutoRefresh();
  } <span class="hljs-keyword">else</span> {
    supabase.auth.stopAutoRefresh();
  }
});
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Crypto <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-crypto'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> SecureStore <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-secure-store'</span>;
<span class="hljs-keyword">import</span> { MMKV } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-mmkv'</span>;
<span class="hljs-keyword">import</span> { isWeb } <span class="hljs-keyword">from</span> <span class="hljs-string">'tamagui'</span>;

<span class="hljs-keyword">const</span> fetchOrGenerateEncryptionKey = (): <span class="hljs-function"><span class="hljs-params">string</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> encryptionKey = SecureStore.getItem(<span class="hljs-string">'session-encryption-key'</span>);

  <span class="hljs-keyword">if</span> (encryptionKey) {
    <span class="hljs-keyword">return</span> encryptionKey;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">const</span> uuid = Crypto.randomUUID();
    SecureStore.setItem(<span class="hljs-string">'session-encryption-key'</span>, uuid);
    <span class="hljs-keyword">return</span> uuid;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> storage = <span class="hljs-keyword">new</span> MMKV({
  id: <span class="hljs-string">'session'</span>,
  encryptionKey: !isWeb ? fetchOrGenerateEncryptionKey() : <span class="hljs-literal">undefined</span>,
});

<span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Remove this workaround for encryption: https://github.com/mrousavy/react-native-mmkv/issues/665</span>
storage.set(<span class="hljs-string">'workaround'</span>, <span class="hljs-literal">true</span>);

<span class="hljs-comment">/**
 * A simple wrapper around MMKV that provides a base API
 * that matches AsyncStorage for use with Supabase.
 */</span>

<span class="hljs-comment">/**
 * Get an item from storage by key
 *
 * @param {string} key of the item to fetch
 * @returns {Promise&lt;string | null&gt;} value for the key as a string or null if not found
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getItem</span>(<span class="hljs-params">key: <span class="hljs-built_in">string</span></span>): <span class="hljs-title">Promise</span>&lt;<span class="hljs-title">string</span> | <span class="hljs-title">null</span>&gt; </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">return</span> storage.getString(key) ?? <span class="hljs-literal">null</span>;
  } <span class="hljs-keyword">catch</span> {
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`Failed to get key "<span class="hljs-subst">${key}</span>" from secure storage`</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-comment">/**
 * Sets an item in storage by key
 *
 * @param {string} key of the item to store
 * @param {string} value of the item to store
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setItem</span>(<span class="hljs-params">key: <span class="hljs-built_in">string</span>, value: <span class="hljs-built_in">string</span></span>): <span class="hljs-title">Promise</span>&lt;<span class="hljs-title">void</span>&gt; </span>{
  <span class="hljs-keyword">try</span> {
    storage.set(key, value);
  } <span class="hljs-keyword">catch</span> {
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`Failed to set key "<span class="hljs-subst">${key}</span>" in secure storage`</span>);
  }
}
<span class="hljs-comment">/**
 * Removes a single item from storage by key
 *
 * @param {string} key of the item to remove
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeItem</span>(<span class="hljs-params">key: <span class="hljs-built_in">string</span></span>): <span class="hljs-title">Promise</span>&lt;<span class="hljs-title">void</span>&gt; </span>{
  <span class="hljs-keyword">try</span> {
    storage.delete(key);
  } <span class="hljs-keyword">catch</span> {
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`Failed to remove key "<span class="hljs-subst">${key}</span>" from secure storage`</span>);
  }
}
</code></pre>
<p>Then create an <code>Auth</code> Component that has conditional, native first segregation of auth providers, via supabase.</p>
<p>Install the following packages <code>yarn add expo-auth-session expo-web-browser</code></p>
<pre><code class="lang-typescript"><span class="hljs-comment">//Auth.tsx</span>

<span class="hljs-keyword">import</span> { makeRedirectUri } <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-auth-session'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> QueryParams <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-auth-session/build/QueryParams'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> WebBrowser <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-web-browser'</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { ActivityIndicator, StyleSheet, View } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> { useMMKVObject, useMMKVString } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-mmkv'</span>;
<span class="hljs-keyword">import</span> { captureSentryException } <span class="hljs-keyword">from</span> <span class="hljs-string">'sentry_telemetry/sentryLogger'</span>;
<span class="hljs-keyword">import</span> { Stack, XStack, YStack } <span class="hljs-keyword">from</span> <span class="hljs-string">'tamagui'</span>;
<span class="hljs-keyword">import</span> MyInput <span class="hljs-keyword">from</span> <span class="hljs-string">'~/components/basic/TextInput'</span>;
<span class="hljs-keyword">import</span> { colors } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/constants/color'</span>;
<span class="hljs-keyword">import</span> { fontSize } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/constants/fontSize'</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/utils/supabase'</span>;
<span class="hljs-keyword">import</span> DottedLine <span class="hljs-keyword">from</span> <span class="hljs-string">'../DottedLine'</span>;
<span class="hljs-keyword">import</span> Text <span class="hljs-keyword">from</span> <span class="hljs-string">'../basic/Text'</span>;
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'../button'</span>;
<span class="hljs-keyword">import</span> Icon <span class="hljs-keyword">from</span> <span class="hljs-string">'../icon/Icon'</span>;
<span class="hljs-keyword">import</span> WebBasedGoogleLogin <span class="hljs-keyword">from</span> <span class="hljs-string">'./WebBasedGoogleLogin'</span>;

WebBrowser.maybeCompleteAuthSession(); <span class="hljs-comment">// required for web only</span>
<span class="hljs-keyword">const</span> redirectTo = makeRedirectUri({});

<span class="hljs-keyword">const</span> createSessionFromUrl = <span class="hljs-keyword">async</span> (url: <span class="hljs-built_in">string</span>) =&gt; {
  <span class="hljs-keyword">const</span> { params, errorCode } = QueryParams.getQueryParams(url);

  <span class="hljs-keyword">if</span> (errorCode) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(errorCode);
  <span class="hljs-keyword">const</span> { access_token, refresh_token } = params;

  <span class="hljs-keyword">if</span> (!access_token) <span class="hljs-keyword">return</span>;

  <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.setSession({
    access_token,
    refresh_token,
  });
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
  <span class="hljs-keyword">return</span> data.session;
};

<span class="hljs-keyword">type</span> AuthProps = {
  isAndroid: <span class="hljs-built_in">boolean</span>;
  isWeb: <span class="hljs-built_in">boolean</span>;
  isIos: <span class="hljs-built_in">boolean</span>;
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Auth</span>(<span class="hljs-params">{ isAndroid, isIos, isWeb }: AuthProps</span>) </span>{
  <span class="hljs-keyword">const</span> toast = useToastController();
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [loginOrSignup, setLoginOrSignup] = useState&lt;<span class="hljs-string">'Login'</span> | <span class="hljs-string">'SignUp'</span>&gt;(<span class="hljs-string">'Login'</span>);
  <span class="hljs-keyword">const</span> [accessToken, setAccessToken] = useMMKVString(<span class="hljs-string">'access_token'</span>);
  <span class="hljs-keyword">const</span> [refreshToken, setRefreshToken] = useMMKVString(<span class="hljs-string">'refresh_token'</span>);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'accessToken value:'</span>, accessToken);
  <span class="hljs-keyword">const</span> [mmkvUser, setMMKVUser] = useMMKVObject&lt;Employee&gt;(<span class="hljs-string">'mmkv_user'</span>);

  <span class="hljs-keyword">const</span> [upsertUser] = useUpsertUserMutation();

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">signInWithEmail</span>(<span class="hljs-params"></span>) </span>{
    setLoading(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> {
        error,
        data: { user, session },
      } = <span class="hljs-keyword">await</span> supabase.auth.signInWithPassword({
        email: email,
        password: password,
      });

      <span class="hljs-keyword">if</span> (error) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(error.message);
      }

      <span class="hljs-keyword">if</span> (session?.access_token) {
        upsertUser({
          fetchPolicy: <span class="hljs-string">'network-only'</span>,

          refetchQueries: [{ query: GetLoggedInUserDocument }],
          onCompleted(data) {
            setMMKVUser(data?.register);
            setAccessToken(session.access_token);

            <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle successful user upsert</span>
          },
          onError(error) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error'</span>, error);
            captureSentryException(<span class="hljs-string">'Error in creating new user'</span>, error <span class="hljs-keyword">as</span> <span class="hljs-built_in">any</span>);
          },
        });
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle error in sign-in with email</span>
    } <span class="hljs-keyword">finally</span> {
      setLoading(<span class="hljs-literal">false</span>);
    }
  }

  <span class="hljs-keyword">const</span> performOAuthGoogle = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.signInWithOAuth({
      provider: <span class="hljs-string">'google'</span>,
      options: {
        redirectTo: redirectTo,
        skipBrowserRedirect: <span class="hljs-literal">true</span>,
        queryParams: {
          access_type: <span class="hljs-string">'offline'</span>,
          prompt: <span class="hljs-string">'consent'</span>,
        },
        scopes: <span class="hljs-string">''</span>,
      },
    });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'OauthGoolge'</span>, data);
    <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'OauthGoolg'</span>, data?.url, redirectTo);
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> WebBrowser.openAuthSessionAsync(data?.url ?? <span class="hljs-string">''</span>, redirectTo);

    <span class="hljs-keyword">if</span> (res.type === <span class="hljs-string">'success'</span>) {
      <span class="hljs-keyword">const</span> { url } = res;
      <span class="hljs-built_in">console</span>.log(url);
      <span class="hljs-keyword">const</span> credential = <span class="hljs-keyword">await</span> createSessionFromUrl(url);
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'after successful token generation'</span>, credential);
      setAccessToken(credential?.access_token);
      setRefreshToken(credential?.refresh_token);
      <span class="hljs-comment">// handleSignInWithGoogle(credential);</span>
    }
  };
  <span class="hljs-keyword">const</span> performOAuthApple = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.signInWithOAuth({
      provider: <span class="hljs-string">'apple'</span>,
      options: {
        redirectTo,
        skipBrowserRedirect: <span class="hljs-literal">true</span>,
      },
    });
    <span class="hljs-built_in">console</span>.log(data?.url);
    <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
    <span class="hljs-built_in">console</span>.log(error);
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> WebBrowser.openAuthSessionAsync(data?.url ?? <span class="hljs-string">''</span>, redirectTo);

    <span class="hljs-keyword">if</span> (res.type === <span class="hljs-string">'success'</span>) {
      <span class="hljs-keyword">const</span> { url } = res;
      <span class="hljs-built_in">console</span>.log(url);
      <span class="hljs-keyword">const</span> credential = <span class="hljs-keyword">await</span> createSessionFromUrl(url);
      <span class="hljs-built_in">console</span>.log(credential?.access_token);
      setAccessToken(credential?.access_token);
      setRefreshToken(credential?.refresh_token);
      <span class="hljs-comment">// handleSignInWithGoogle(credential);</span>
    }
  };
  <span class="hljs-comment">// async function handleSignInWithGoogle(session: Session) {</span>
  <span class="hljs-comment">//   const { data, error } = await supabase.auth.signInWithIdToken({</span>
  <span class="hljs-comment">//     provider: 'google',</span>
  <span class="hljs-comment">//     token: response.credential,</span>
  <span class="hljs-comment">//     nonce: 'NONCE', // must be the same one as provided in data-nonce (if any)</span>
  <span class="hljs-comment">//   });</span>
  <span class="hljs-comment">// }</span>
  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">signUpWithEmail</span>(<span class="hljs-params"></span>) </span>{
    setLoading(<span class="hljs-literal">true</span>);
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> {
        data: { session },
        error,
      } = <span class="hljs-keyword">await</span> supabase.auth.signUp({
        email: email,
        password: password,
      });

      <span class="hljs-keyword">if</span> (error) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(error.message);
      }

      <span class="hljs-built_in">console</span>.log(session?.user);
      <span class="hljs-keyword">if</span> (!session) {
        <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Show email verification prompt</span>
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle error in sign-up with email</span>
    } <span class="hljs-keyword">finally</span> {
      setLoading(<span class="hljs-literal">false</span>);
    }
  }

  <span class="hljs-keyword">return</span> (
    &lt;Stack w={<span class="hljs-string">'80%'</span>} alignSelf=<span class="hljs-string">"center"</span>&gt;
      &lt;YStack w={<span class="hljs-string">'90%'</span>} gap={<span class="hljs-number">10</span>} alignSelf=<span class="hljs-string">"center"</span>&gt;
        &lt;MyInput
          label=<span class="hljs-string">"Email"</span>
          <span class="hljs-comment">// leftIcon={{ type: 'font-awesome', name: 'envelope' }}</span>
          onChangeText={<span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> setEmail(text)}
          value={email}
          placeholder=<span class="hljs-string">"Email"</span>
          autoCapitalize={<span class="hljs-string">'none'</span>}
        /&gt;

        &lt;MyInput
          label=<span class="hljs-string">"Password"</span>
          <span class="hljs-comment">// leftIcon={{ type: 'font-awesome', name: 'lock' }}</span>
          onChangeText={<span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> setPassword(text)}
          value={password}
          secureTextEntry={<span class="hljs-literal">true</span>}
          placeholder=<span class="hljs-string">"Password"</span>
          autoCapitalize={<span class="hljs-string">'none'</span>}
        /&gt;
        {loginOrSignup === <span class="hljs-string">'Login'</span> ? (
          &lt;View style={[styles.verticallySpaced, styles.mt20]}&gt;
            &lt;Button
              backgroundColor={!email || !password ? <span class="hljs-string">'$background'</span> : <span class="hljs-string">'$primary'</span>}
              disabled={!email || !password}
              onPress={<span class="hljs-function">() =&gt;</span> signInWithEmail()}&gt;
              {loading ? (
                &lt;ActivityIndicator color={colors.primary} /&gt;
              ) : (
                &lt;Text variant=<span class="hljs-string">"semi-bold"</span> color={!email || !password ? <span class="hljs-string">'black'</span> : <span class="hljs-string">'white'</span>}&gt;
                  Log <span class="hljs-keyword">in</span>
                &lt;/Text&gt;
              )}
            &lt;/Button&gt;
          &lt;/View&gt;
        ) : (
          &lt;View style={styles.verticallySpaced}&gt;
            &lt;Button
              backgroundColor={!email || !password ? <span class="hljs-string">'$background'</span> : <span class="hljs-string">'$primary'</span>}
              disabled={!email || !password}
              onPress={<span class="hljs-function">() =&gt;</span> signUpWithEmail()}&gt;
              {loading ? (
                &lt;ActivityIndicator color={colors.primary} /&gt;
              ) : (
                &lt;Text variant=<span class="hljs-string">"semi-bold"</span> color={!email || !password ? <span class="hljs-string">'black'</span> : <span class="hljs-string">'white'</span>}&gt;
                  Register
                &lt;/Text&gt;
              )}
            &lt;/Button&gt;
          &lt;/View&gt;
        )}
      &lt;/YStack&gt;

      {isIos &amp;&amp; !isAndroid ? (
        &lt;WebBasedGoogleLogin /&gt;
      ) : (
        &lt;View style={styles.verticallySpaced}&gt;
          &lt;Button
            w={<span class="hljs-string">'70%'</span>}
            onPress={performOAuthGoogle}
            alignSelf=<span class="hljs-string">"center"</span>
            style={styles.googleBtn}&gt;
            &lt;Text color={<span class="hljs-string">'white'</span>} variant=<span class="hljs-string">"bold"</span>&gt;
              Sign <span class="hljs-keyword">in</span> With Google
            &lt;/Text&gt;
          &lt;/Button&gt;
        &lt;/View&gt;
      )}

      {isWeb &amp;&amp; (
        &lt;View style={styles.verticallySpaced}&gt;
          &lt;Button w={<span class="hljs-string">'70%'</span>} alignSelf=<span class="hljs-string">"center"</span> onPress={performOAuthApple} style={styles.appleBtn}&gt;
            &lt;Text color={<span class="hljs-string">'white'</span>} variant=<span class="hljs-string">"semi-bold"</span>&gt;
              Sign <span class="hljs-keyword">in</span> With Apple
            &lt;/Text&gt;
          &lt;/Button&gt;
        &lt;/View&gt;
      )}
      &lt;DottedLine /&gt;

      &lt;XStack gap={<span class="hljs-number">4</span>} alignSelf=<span class="hljs-string">"center"</span>&gt;
        &lt;Text
          onPress={<span class="hljs-function">() =&gt;</span> setLoginOrSignup(loginOrSignup === <span class="hljs-string">'Login'</span> ? <span class="hljs-string">'SignUp'</span> : <span class="hljs-string">'Login'</span>)}
          style={{
            textAlign: <span class="hljs-string">'center'</span>,
            color: colors.primary,
            fontSize: fontSize.lg,
            fontWeight: <span class="hljs-string">'500'</span>,
          }}&gt;
          {loginOrSignup === <span class="hljs-string">'Login'</span> ? <span class="hljs-string">'Sign Up'</span> : <span class="hljs-string">'Log in'</span>}
        &lt;/Text&gt;
      &lt;/XStack&gt;
    &lt;/Stack&gt;
  );
}
<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    flex: <span class="hljs-number">1</span>,
    alignItems: <span class="hljs-string">'center'</span>,
  },
  emailInput: {
    marginBottom: <span class="hljs-number">10</span>,
  },
  verticallySpaced: {
    paddingTop: <span class="hljs-number">4</span>,
    paddingBottom: <span class="hljs-number">4</span>,
    alignSelf: <span class="hljs-string">'stretch'</span>,
  },
  mt20: {
    marginTop: <span class="hljs-number">20</span>,
  },
  appleBtn: {
    backgroundColor: colors.black,
    borderRadius: <span class="hljs-number">100</span>,
    height: <span class="hljs-number">50</span>,
  },
  googleBtn: {
    backgroundColor: colors.orange,
    borderRadius: <span class="hljs-number">100</span>,
    height: <span class="hljs-number">50</span>,
  },
});
</code></pre>
<p>Now create respective, <code>NativeAppleSignIn.tsx</code> and <code>NativeGoogleSignIn.tsx</code>. Install the required packages by running <code>yarn add expo-apple-authentication @react-native-google-signin/google-signin</code></p>
<pre><code class="lang-typescript"><span class="hljs-comment">//NativeGoogleSignIn.tsx</span>
<span class="hljs-keyword">import</span> {
  GoogleSignin,
  GoogleSigninButton,
  statusCodes,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-native-google-signin/google-signin'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'core-js/stable/atob'</span>;
<span class="hljs-keyword">import</span> {
  Employee,
  GetLoggedInUserDocument,
  useRegisterUserMutation,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'generated/hooks_and_more'</span>;
<span class="hljs-keyword">import</span> jwtDecode <span class="hljs-keyword">from</span> <span class="hljs-string">'jwt-decode'</span>;
<span class="hljs-keyword">import</span> { Platform } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> { useMMKVObject, useMMKVString } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-mmkv'</span>;
<span class="hljs-keyword">import</span> { captureSentryException } <span class="hljs-keyword">from</span> <span class="hljs-string">'sentry_telemetry/sentryLogger'</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/utils/supabase'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">GoogleSignIn</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [accessToken, setAccessToken] = useMMKVString(<span class="hljs-string">'access_token'</span>);
  <span class="hljs-keyword">const</span> [refreshToken, setRefreshToken] = useMMKVString(<span class="hljs-string">'refresh_token'</span>);
  <span class="hljs-keyword">const</span> [mmkvUser, setMMKVUser] = useMMKVObject&lt;Employee&gt;(<span class="hljs-string">'mmkv_user'</span>);
  <span class="hljs-keyword">const</span> [registerUser, { data: userResponse, loading: registerLoading }] =
    useRegisterUserMutation();

  GoogleSignin.configure({
    iosClientId: process.env.EXPO_PUBLIC_IOS_GOOGLE_CLIENT_ID,
    webClientId: process.env.EXPO_PUBLIC_WEB_GOOGLE_CLIENT_ID,
    offlineAccess: <span class="hljs-literal">true</span>,
    scopes: [<span class="hljs-string">'profile'</span>, <span class="hljs-string">'email'</span>],
  });
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">onPress</span>(<span class="hljs-params"></span>)</span>{
          <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">await</span> GoogleSignin.hasPlayServices();
            <span class="hljs-keyword">const</span> userInfo = <span class="hljs-keyword">await</span> GoogleSignin.signIn();
            <span class="hljs-keyword">const</span> decodedToken = jwtDecode(userInfo.idToken);
            <span class="hljs-keyword">const</span> nonceFromToken = decodedToken.nonce;
            <span class="hljs-built_in">console</span>.log(nonceFromToken);
            <span class="hljs-keyword">if</span> (userInfo.idToken) {
              <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.signInWithIdToken({
                provider: <span class="hljs-string">'google'</span>,
                token: userInfo.idToken,
              });

              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'google native'</span>, error, data);
              setAccessToken(data?.session?.access_token || <span class="hljs-string">''</span>);
              setRefreshToken(data?.session?.refresh_token || <span class="hljs-string">''</span>);
              registerUser({
                refetchQueries: [{ query: GetLoggedInUserDocument }],
                onCompleted(data, clientOptions) {
                  setMMKVUser(data?.register);
                  <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle successful user registration</span>
                },
                onError(error, clientOptions) {
                  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error'</span>, error);
                  captureSentryException(
                    <span class="hljs-string">'Error in creating new user[Native Google SignIn]'</span>,
                    error <span class="hljs-keyword">as</span> <span class="hljs-built_in">any</span>
                  );
                },
              });
            } <span class="hljs-keyword">else</span> {
              <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'no ID token present!'</span>);
            }
          } <span class="hljs-keyword">catch</span> (error: <span class="hljs-built_in">any</span>) {
            <span class="hljs-keyword">if</span> (error.code === statusCodes.SIGN_IN_CANCELLED) {
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'user cancelled the sign in'</span>, error);
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (error.code === statusCodes.IN_PROGRESS) {
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'user cancelled the login flow'</span>, error);
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'play services not available or outdated'</span>, error);
            } <span class="hljs-keyword">else</span> {
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'some other error happened'</span>, error);
            }
          }
        }}
  <span class="hljs-keyword">if</span> (Platform.OS === <span class="hljs-string">'android'</span>) {
    <span class="hljs-keyword">return</span> (
      &lt;GoogleSigninButton
        size={GoogleSigninButton.Size.Standard}
        color={GoogleSigninButton.Color.Dark}
        onPress={onPress}
      /&gt;
    );
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<pre><code class="lang-typescript"><span class="hljs-comment">//NativeAppleSignIn.tsx</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> AppleAuthentication <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-apple-authentication'</span>;
<span class="hljs-keyword">import</span> {
  Employee,
  GetLoggedInUserDocument,
  useRegisterUserMutation,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'generated/hooks_and_more'</span>;
<span class="hljs-keyword">import</span> { Platform } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> { useMMKVObject, useMMKVString } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-mmkv'</span>;
<span class="hljs-keyword">import</span> { captureSentryException } <span class="hljs-keyword">from</span> <span class="hljs-string">'sentry_telemetry/sentryLogger'</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/utils/supabase'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AppleSignIn</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [accessToken, setAccessToken] = useMMKVString(<span class="hljs-string">'access_token'</span>);
  <span class="hljs-keyword">const</span> [refreshToken, setRefreshToken] = useMMKVString(<span class="hljs-string">'refresh_token'</span>);
  <span class="hljs-keyword">const</span> [mmkvUser, setMMKVUser] = useMMKVObject&lt;Employee&gt;(<span class="hljs-string">'mmkv_user'</span>);
  <span class="hljs-keyword">const</span> [registerUser, { data: userResponse, loading: registerLoading }] =
    useRegisterUserMutation();

  <span class="hljs-keyword">const</span> handleAppleSignIn = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> credential = <span class="hljs-keyword">await</span> AppleAuthentication.signInAsync({
        requestedScopes: [
          AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
          AppleAuthentication.AppleAuthenticationScope.EMAIL,
        ],
      });
      <span class="hljs-built_in">console</span>.log(credential);
      <span class="hljs-keyword">if</span> (credential.identityToken) {
        <span class="hljs-keyword">const</span> {
          error,
          data: { user, session },
        } = <span class="hljs-keyword">await</span> supabase.auth.signInWithIdToken({
          provider: <span class="hljs-string">'apple'</span>,
          token: credential.identityToken,
        });
        <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify({ error, user }, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>));
        <span class="hljs-keyword">if</span> (!error) {
          setAccessToken(session?.access_token || <span class="hljs-string">''</span>);
          setRefreshToken(session?.refresh_token || <span class="hljs-string">''</span>);
          registerUser({
            refetchQueries: [{ query: GetLoggedInUserDocument }],
            onCompleted(data, clientOptions) {
              setMMKVUser(data?.register);
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'on registered in Native Apple Login'</span>, accessToken);
            },
            onError(error, clientOptions) {
              <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error'</span>, error);
              captureSentryException(<span class="hljs-string">'Error in creating new user'</span>, error <span class="hljs-keyword">as</span> <span class="hljs-built_in">any</span>);
            },
          });
        }
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'No identityToken.'</span>);
      }
    } <span class="hljs-keyword">catch</span> (e) {
      <span class="hljs-keyword">if</span> (e.code === <span class="hljs-string">'ERR_REQUEST_CANCELED'</span>) {
        <span class="hljs-comment">// handle that the user canceled the sign-in flow</span>
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// handle other errors</span>
      }
    }
  };

  <span class="hljs-keyword">if</span> (Platform.OS === <span class="hljs-string">'ios'</span>) {
    <span class="hljs-keyword">return</span> (
      &lt;AppleAuthentication.AppleAuthenticationButton
        buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
        buttonStyle={AppleAuthentication.AppleAuthenticationButtonStyle.BLACK}
        cornerRadius={<span class="hljs-number">5</span>}
        style={{ width: <span class="hljs-number">200</span>, height: <span class="hljs-number">64</span> }}
        onPress={handleAppleSignIn}
      /&gt;
    );
  }
  <span class="hljs-keyword">return</span> &lt;&gt;{<span class="hljs-comment">/* Implement Android Auth options. */</span>}&lt;/&gt;;
}
</code></pre>
<blockquote>
<p>There was an issue that I face with native Google sign in on iOS for quite long and chose to drop it for a while and use an alternative that supports cross-platform auth.<br />For that, create a <code>WebBasedGoogleLogin.tsx</code> file and use it in the <code>Auth</code> component universally. Add the packages by running</p>
</blockquote>
<pre><code class="lang-typescript"><span class="hljs-comment">//WebBasedGoogleLogin.tsx</span>
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> Google <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-auth-session/providers/google'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> WebBrowser <span class="hljs-keyword">from</span> <span class="hljs-string">'expo-web-browser'</span>;
<span class="hljs-keyword">import</span> {
  Employee,
  GetLoggedInUserDocument,
  useRegisterUserMutation,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'generated/hooks_and_more'</span>;
<span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> { useMMKVObject, useMMKVString } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-mmkv'</span>;
<span class="hljs-keyword">import</span> { captureSentryException } <span class="hljs-keyword">from</span> <span class="hljs-string">'sentry_telemetry/sentryLogger'</span>;
<span class="hljs-keyword">import</span> { setRefreshToken } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/hooks/storage/token'</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">'~/utils/supabase'</span>;
<span class="hljs-keyword">import</span> Text <span class="hljs-keyword">from</span> <span class="hljs-string">'../basic/Text'</span>;
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'../button'</span>;

WebBrowser.maybeCompleteAuthSession();
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">WebBasedGoogleLogin</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [userInfo, setUserInfo] = useState();
  <span class="hljs-keyword">const</span> [mmkvUser, setMMKVUser] = useMMKVObject(<span class="hljs-string">'mmkv_user'</span>);
  <span class="hljs-keyword">const</span> [accessToken, setAccessToken] = useMMKVString(<span class="hljs-string">'access_token'</span>);
  <span class="hljs-keyword">const</span> [registerUser, { data: userResponse, loading: registerLoading }] =
    useRegisterUserMutation();
  <span class="hljs-keyword">const</span> [request, response, promptAsync] = Google.useAuthRequest({
    androidClientId: process.env.EXPO_PUBLIC_ANDROID_GOOGLE_CLIENT_ID,
    webClientId: process.env.EXPO_PUBLIC_WEB_GOOGLE_CLIENT_ID,
    iosClientId: process.env.EXPO_PUBLIC_IOS_GOOGLE_CLIENT_ID,
  });

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// setAccessToken('');</span>

    handleSignInWithGoogle();
  }, [response]);

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleSignInWithGoogle</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (!mmkvUser) {
      <span class="hljs-keyword">if</span> (response?.type === <span class="hljs-string">'success'</span>) {
        <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.auth.signInWithIdToken({
          provider: <span class="hljs-string">'google'</span>,
          token: response?.authentication?.idToken,
        });

        setAccessToken(data?.session?.access_token);
        setRefreshToken(data?.session?.refresh_token);
        setMMKVUser(data?.session?.user);
      }
    } <span class="hljs-keyword">else</span> {
      setMMKVUser(<span class="hljs-string">''</span>);

      <span class="hljs-comment">//error message</span>
    }
  }

  <span class="hljs-keyword">const</span> getUserInfo = <span class="hljs-keyword">async</span> (token) =&gt; {
    <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://www.googleapis.com/userinfo/v2/me'</span>, {
        headers: {
          Authorization: <span class="hljs-string">`Bearer <span class="hljs-subst">${token}</span>`</span>,
        },
      });
      <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> res.json();
      <span class="hljs-built_in">console</span>.log(user);
     <span class="hljs-comment">//db upsert user</span>
      registerUser({
        refetchQueries: [{ query: GetLoggedInUserDocument }],
        onCompleted(data, clientOptions) {
          setMMKVUser(data?.register);
          setUserInfo(data?.register);
          <span class="hljs-comment">// user &amp;&amp; getAccessToken() &amp;&amp; navigation.replace('SetupYourOrganization');</span>
        },
        onError(error, clientOptions) {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'error'</span>, error);
          captureSentryException(<span class="hljs-string">'Error in creating new user'</span>, error <span class="hljs-keyword">as</span> <span class="hljs-built_in">any</span>);
        },
      });
    } <span class="hljs-keyword">catch</span> (error) {}
  };

  <span class="hljs-keyword">return</span> (
    &lt;&gt;
      &lt;Text&gt;{<span class="hljs-built_in">JSON</span>.stringify(userInfo)}&lt;/Text&gt;
      &lt;Button w={<span class="hljs-string">'70%'</span>} alignSelf=<span class="hljs-string">"center"</span> onPress={<span class="hljs-function">() =&gt;</span> promptAsync()} style={styles.googleBtn}&gt;
        &lt;Text variant=<span class="hljs-string">"semi-bold"</span> color={<span class="hljs-string">'white'</span>}&gt;
          Sign <span class="hljs-keyword">in</span> <span class="hljs-keyword">with</span> Google
        &lt;/Text&gt;
      &lt;/Button&gt;
    &lt;/&gt;
  );
}

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  googleBtn: {
    backgroundColor: <span class="hljs-string">'#4285F4'</span>, <span class="hljs-comment">// Google's brand color</span>
    borderRadius: <span class="hljs-number">4</span>,
    paddingVertical: <span class="hljs-number">12</span>,
    paddingHorizontal: <span class="hljs-number">16</span>,
    elevation: <span class="hljs-number">3</span>,
  },
});
</code></pre>
<p>All of these components only work, if I pass the <code>accessToken</code> in the headers of my fetcher function, and to do secure API calls, add this to your fetcher headers,</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> JWT_TOKEN = (<span class="hljs-keyword">await</span> supabase.auth.getSession()).data.session?.access_token;
</code></pre>
<p>Make sure to add the following environment variables</p>
<pre><code class="lang-plaintext">//.env
EXPO_PUBLIC_SUPABASE_URL=
EXPO_PUBLIC_SUPABASE_ANON_KEY=
EXPO_PUBLIC_IOS_GOOGLE_CLIENT_ID= 
EXPO_PUBLIC_WEB_GOOGLE_CLIENT_ID=
EXPO_PUBLIC_ANDROID_GOOGLE_CLIENT_ID=
EXPO_PUBLIC_SUPABASE_REDIRECT_URI=
</code></pre>
<p>I've followed the guides available on various platforms and github issues, to be able to work on this. Supabase-Auth is a marvelous library, it has every major auth provider of the internet, Supabase auth client is written in go, please do give it a ⭐ on <a target="_blank" href="https://github.com/supabase/auth">github</a>.</p>
<ul>
<li><p><a target="_blank" href="https://supabase.com/docs/guides/auth/social-login/auth-apple?queryGroups=platform&amp;platform=react-native">https://supabase.com/docs/guides/auth/social-login/auth-apple?queryGroups=platform&amp;platform=react-native</a></p>
</li>
<li><p><a target="_blank" href="https://supabase.com/docs/guides/auth/social-login/auth-google?queryGroups=platform&amp;platform=react-native">https://supabase.com/docs/guides/auth/social-login/auth-google?queryGroups=platform&amp;platform=react-native</a></p>
</li>
<li><p><a target="_blank" href="https://ignitecookbook.com/docs/recipes/Authentication/">https://ignitecookbook.com/docs/recipes/Authentication/</a></p>
</li>
</ul>
<hr />
<p>Thanks for reading this tutorial, If you found it useful. Let me know. If you have any doubts, do reach out to me on twitter @<a target="_blank" href="https://www.twitter.com/agrit_tiwari">Agrit Tiwari</a><br />Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[Schema Driven Development]]></title><description><![CDATA[Bringing a project to life needs a clear plan. You start by thinking about the features you want and get into the nitty-gritty details. When you have a clear picture, implementing the project becomes much smoother. A big part of this involves figurin...]]></description><link>https://tech-blog.agrittiwari.com/schema-driven-development</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/schema-driven-development</guid><category><![CDATA[schema]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[Product Design]]></category><category><![CDATA[Apollo GraphQL]]></category><category><![CDATA[Dgraph]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Fri, 02 Feb 2024 15:41:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706888036905/33bdfe67-0c09-47d1-81f6-aad973ffa400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Bringing a project to life needs a clear plan. You start by thinking about the features you want and get into the nitty-gritty details. When you have a clear picture, implementing the project becomes much smoother. A big part of this involves figuring out how to handle the data – what it looks like, how it's connected, and what events it triggers. This is the basic foundation for any tech product, no matter how fancy or important.</p>
<p>Most of the time, the focus is on the data and its relationships, which then generates more data. The rest, like creating a great user experience, builds on top of that. Every product is essentially a game played with data, even the really complex ones.</p>
<p>To turn your ideas into reality, everyone involved – UI designers, UX designers, and developers – needs to understand the data and how it's connected. This understanding is especially crucial for building complex applications dealing with a lot of data. Graphs become handy tools for creating a mental map of how your data is related, leading to better user design and experiences.</p>
<p>GraphQL Schema is like a common language that helps everyone on the team be productive and clear right from the beginning. There's a whole ecosystem supporting your journey in modeling data. GraphQL Schema acts as this shared tool that guides the development of features from the initial idea to the final product, making sure everyone is on the same page. Let's explore the world of Schema-driven development together.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694277736802/fbdf8505-8852-4c4b-9dab-bf446bb851f5.png" alt class="image--right mx-auto mr-0" /></p>
<h1 id="heading-schema">Schema:</h1>
<p>You can start writing your schema/data model in just as fast as you would describe data structure in English language. The key aspects is to define the data by naming them with context of actually what it represents. We start by defining a node like User;</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">type</span> User{
<span class="hljs-symbol">id:</span>ID!
<span class="hljs-symbol">name:</span>String
<span class="hljs-symbol">email:</span>String
<span class="hljs-symbol">friends:</span>[User]
<span class="hljs-symbol">isEighteenYearsOld:</span>Boolean
}
</code></pre>
<p>and you can define relationships across entities, which actually is the business logic.</p>
<h3 id="heading-example">Example:</h3>
<p>Consider a basic Expense Share Tracker app, that tracks share of expense among friends, what you would want is to track every expense, who paid for it ,how much and who were part of that transaction. So this boils down to this schema of any transaction</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">type</span> Transaction{
<span class="hljs-symbol">id:</span>ID!
<span class="hljs-symbol">description:</span>String
<span class="hljs-symbol">amount:</span>Number
<span class="hljs-symbol">sharedInto:</span>[User]
<span class="hljs-symbol">paidBy:</span>User
}
</code></pre>
<h2 id="heading-using-a-codegen-tooling">Using a codegen tooling</h2>
<p>You can generate a graphql API, with codegen tooling, be it codegen tools by <a target="_blank" href="https://guild.dev">the-guild.dev</a> or a complete backend solution like Hasura or dGraph.</p>
<p>You can have the API up and running very quickly that matches each and every requirement of your app, like this one.</p>
<p>generate API: all the basic queries and mutations</p>
<pre><code class="lang-typescript">---------
getUser ( id ID! ) User
ADD QUERY
queryUser ( filter UserFilter, order UserOrder, first Int, offset Int ) [User]
ADD QUERY
aggregateUser ( filter UserFilter ) UserAggregateResult
ADD QUERY
getTransaction ( id ID! ) Transaction
ADD QUERY
queryTransaction ( filter TransactionFilter, order TransactionOrder, first Int, offset Int ) [Transaction]
ADD QUERY
aggregateTransaction ( filter TransactionFilter ) TransactionAggregateResult
----------
addUser ( input [AddUserInput!]! ) AddUserPayload
ADD QUERY
updateUser ( input UpdateUserInput! ) UpdateUserPayload
ADD QUERY
deleteUser ( filter UserFilter! ) DeleteUserPayload
ADD QUERY
addTransaction ( input [AddTransactionInput!]! ) AddTransactionPayload
ADD QUERY
updateTransaction ( input UpdateTransactionInput! ) UpdateTransactionPayload
ADD QUERY
deleteTransaction ( filter TransactionFilter! ) DeleteTransactionPayload
</code></pre>
<h2 id="heading-iteration-cycle-design-drives-schema">Iteration cycle: Design Drives Schema</h2>
<p>Product development cycles thrive when there's a swift iteration process, translating requirements and clarity into a schema promptly.</p>
<p>There's a delay in frontend development, but diving deep into detailed discussions about requirements during the design iteration phase can be incredibly beneficial. This process involves translating those requirements into a schema. The payoff is worth it! Building the user interface becomes a breeze when you use a typed GraphQL schema and generate corresponding APIs. Naming variables becomes more meaningful in context, and the entire development experience becomes solidly end-to-end typed, providing a fantastic experience for developers.</p>
<hr />
<p>Do share relevant blogs in the comments if you have some different processes followed in your product cycle. Thanks</p>
]]></content:encoded></item><item><title><![CDATA[Raycast extension for Hashnode]]></title><description><![CDATA[GraphQL is an absolute marvel in the realm of software technology. My journey with GraphQL began about two months ago, and I must admit, it initially felt like diving into the deep end. As I navigated the complexities, I found myself delving into RES...]]></description><link>https://tech-blog.agrittiwari.com/raycast-extension-for-hashnode</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/raycast-extension-for-hashnode</guid><category><![CDATA[APIHackathon]]></category><category><![CDATA[raycast]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Thu, 01 Feb 2024 09:31:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706780295205/490a8d75-edb0-4dd8-8428-fd3d2a8cd0e2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>GraphQL is an absolute marvel in the realm of software technology. My journey with GraphQL began about two months ago, and I must admit, it initially felt like diving into the deep end. As I navigated the complexities, I found myself delving into REST APIs, only to circle back last year and construct an entire app from scratch, complete with a GraphQL layer and more. Hashnode, being my go-to platform during my learning phase a year ago, was where I envisioned sharing my insights, especially on the fascinating world of GraphQL.</p>
<p>Although my GraphQL blogs are still lingering in the drafts, the allure of coding GraphQL APIs in projects is something I can't resist any day. Enter Hashnode, presenting a golden opportunity by unveiling its API to the public.</p>
<p>As for Raycast, I first heard about it during its X launch. Admittedly, I wasn't part of the Mac ecosystem then, missing out on understanding the unique problems it solves for Mac users.</p>
<p>Now, imagine bringing all these elements together into a delightful smoothie. Enter the Raycast extension for Hashnode – a potential game-changer. With the public API at your fingertips, imagine the possibilities and the seamless user experience it could offer. Don't miss out on this innovative way of publishing technical blogs; it might just be the missing piece you've been waiting for!</p>
<h3 id="heading-requisite">Requisite:</h3>
<p>User would need hashnode username and <a target="_blank" href="https://hashnode.com/settings/developer">PAT (Personal Access Token)</a> 👆</p>
<h2 id="heading-features">Features</h2>
<p>Profile Section to share articles and look up personal articles quickly</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706777845011/867492c7-c0b8-4a26-8195-d01d29ba0eff.gif" alt class="image--center mx-auto" /></p>
<p>Publish Command to publish articles to your publications right from your dock.</p>
<ol>
<li><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706776837335/f23beef6-c96d-4b37-8960-6db478983737.png" alt class="image--center mx-auto" /></li>
</ol>
<p>Search Command to search blogs from subscribed publications</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706777765048/31046e2c-1543-41e9-9f02-12b45f6342fd.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-future-scope-of-the-extension">Future Scope of the extension</h2>
<p>As the <a target="_blank" href="https://gql.hashnode.com"><mark>hashnode API</mark></a> evolves, and it adds more power to customize search and filter, the scope of the extension if mainly going to be focused on improving user experience.</p>
<ul>
<li><p>Introducing Oauth with hashnode.</p>
</li>
<li><p>Better Insights on profile page about blog analytics.</p>
</li>
<li><p>More configurable form elements to publish media rich blogs right from your dock.</p>
</li>
<li><p>Draft first approach for your blogs.</p>
</li>
<li><p>Powerful Search based on tags and fuzzy Search over title, author and publication</p>
</li>
</ul>
<h2 id="heading-try-out-the-extension-today-on-raycasthttpswwwraycastcomagrittiwarihashnode-search-and-publish">Try out the extension today on <a target="_blank" href="https://www.raycast.com/agrittiwari/hashnode-search-and-publish">Raycast</a> : 👆</h2>
<p>Send some feedback to me on Hashnode or Github: <a target="_blank" href="https://github.com/agrittiwari/hashnode-search-and-publish">https://github.com/agrittiwari/hashnode-search-and-publish</a> ⭐  </p>
<p>Install Raycast Extension : <a target="_blank" href="https://www.raycast.com/agrittiwari/hashnode-search-and-publish">https://www.raycast.com/agrittiwari/hashnode-search-and-publish</a></p>
<p>Thank you ✨</p>
]]></content:encoded></item><item><title><![CDATA[React Native Internals for Web Developers]]></title><description><![CDATA[Learn Mobile Development with React Native
Web developers often find themselves going between the realms of the client-side and server-side. And both are quite complex and abstracted as the usecases have grown with the ecosystem and community. 

Ther...]]></description><link>https://tech-blog.agrittiwari.com/react-native-internals-for-web-developers</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/react-native-internals-for-web-developers</guid><category><![CDATA[React Native]]></category><category><![CDATA[Expo]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[architecture]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Mon, 03 Oct 2022 05:57:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664776359730/-Yu8ok7b7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-learn-mobile-development-with-react-native">Learn Mobile Development with React Native</h1>
<p>Web developers often find themselves going between the realms of the client-side and server-side. And both are quite complex and abstracted as the usecases have grown with the ecosystem and community. </p>
<blockquote>
<p>There's also mobile development that shoots off from the client-side library React –  an open source, cross-platform framework called <a target="_blank" href="https://www.reactnative.dev/">React Native</a>. This is the frontend of cross-platform mobile development with various APIs to support smooth cross-platform development.</p>
</blockquote>
<p>The developer experience has changed and has moved closer to the Web with React Native. It has a React-based UI and component-based rendering, though it has its own React Native elements for its UI. The UI development and state management is based on React hooks as well. </p>
<p>Its whole integration to back ends and third party APIs is well-supported in JavaScript, which is the core language of web development.</p>
<h2 id="heading-react-native-uses-javascript">React Native Uses JavaScript 🎉</h2>
<p><iframe src="https://giphy.com/embed/bVcpc4QFNUxkOfCw0E" width="480" height="416" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/rainpomelo-littlehuman-wihte-bVcpc4QFNUxkOfCw0E">via GIPHY</a></p>
React Native is a JavaScript cross-platform mobile framework. It allows developers to code in JavaScript and TypeScript to create apps with beautiful UIs. It can also handle heavy state management, lets you build elegant animations, and has many native functionalities and features.<p></p>
<p>And there is no web without JS – so if you're a web developer, you already have a solid foundation of developing in Javascript. React adds a layer of component architecture, and with that you can start building apps in React Native.</p>
<h2 id="heading-bundler">Bundler 🍬</h2>
<p>As a web developer, it is obvious to use a javascript bundler as your codebase grows into large number of  modules. A fantastic feature of a bundler is that it generates a dependency graph as it traverses your first code files. This implies that beginning with the entry point you specified, the module bundler keeps track of both your source files’ dependencies and third-party dependencies. This dependency graph guarantees that all source and associated code files are kept up to date and error-free.</p>
<p>There are many bundlers known to web developers like <a target="_blank" href="https://webpack.js.org/">Webpack</a>, <a target="_blank" href="https://parceljs.org/">Parcel</a>, <a target="_blank" href="https://rollupjs.org/guide/en/">Rollup</a>, <a target="_blank" href="https://vitejs.dev/">Vite.js</a> etc., which basically promotes Asset optimization, developer productivity, fastness and framework agnostism</p>
<p>The JavaScript bundler for React Native is called 🚇 <a target="_blank" href="https://facebook.github.io/metro/">Metro</a> It is the default bundler for React Native which was the part of reactnative codebase but later separated and open-sourced dor community  driven growth.
 It takes in an entry file and various options, and gives you back a single JavaScript file that includes all your code and its dependencies. Just like web bundlers</p>
<p>Metro has three separate stages in its bundling process:
<a target="_blank" href="https://facebook.github.io/metro/docs/concepts">Resolution, Transformation, and Serialization</a></p>
<p>There is another lightweight bundler called <a target="_blank" href="https://re-pack.netlify.app/">Repack</a> in reactnative ecosystem. </p>
<h2 id="heading-storage-system">Storage System 🌐💾</h2>
<p>Browser based apps and React Native apps have a similar storage system to store information for the app runtime and globally for various usecase like session for authenticated user, Long form data over multiple pages, low network response, store accessTokens or cookies, etc.</p>
<p>Local/Session storage for Web Developers
Web storage objects localStorage and sessionStorage allow to save key/value pairs in the browser. <a target="_blank" href="https://javascript.info/localstorage">Read more here</a></p>
<p>Async Storage and MMKV for React Native Developers. AsyncStorage is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app. <a target="_blank" href="https://react-native-async-storage.github.io/async-storage/docs/usage/">Read more here</a>
MMKV is an efficient, small mobile key-value storage framework developed by WeChat.
<a target="_blank" href="https://github.com/mrousavy/react-native-mmkv">Read more here</a></p>
<h2 id="heading-databases">Databases 🗃️</h2>
<p>There are enormous variety of databases these days and it is very confusing to choose a database in web development already. Many Famous and effective dbs are MySQL,  MongoDB, Oracle, Airtable and Firebase.</p>
<p>React Native has a good support with MySQL and  Realm by MongoDB.
There are two new cloud databases Supabase and PlanetScale, which you can try with your react native apps.</p>
<h2 id="heading-backend">Backend</h2>
<p>The backend of a react native app is well supported by NodeJS and PHP. NodeJS is a Javascript based backend and it has super compatibility with React based frontend. 
PHP is a scripting backend language, commonly used with Laravel framework. Both Node and PHP are well know backends to web developers.</p>
<h2 id="heading-navigation-routing">Navigation/ Routing</h2>
<p>Web developers are well acquainted with url based navigation. To put it simply, when you to navigate to a different page on a web app, there is a definite route for that page on the web. For example, LOGIN page has <code>/www.example.com/login</code> url and SIGNUP page has <code>/www.example.com/signup</code> url.</p>
<p>But in React Native, there is no url bar, so the architecture that React Native follows is of Screens navigational flow. There are Stacks, Drawers and Tab based Navigation that is followed in React Native, a standard set by <a target="_blank" href="https://reactnavigation.org/">React Navigation</a> </p>
<p><iframe src="https://giphy.com/embed/moO9geVYZG4yGfKkQd" width="222" height="480" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/android-motion-graphics-ios-moO9geVYZG4yGfKkQd">via GIPHY</a></p><p></p>
<blockquote>
<p>Expo team is trying to introduce, what we call, File based routing inside React Native and this will advance the world towards truly cross-platform development. You can follow up on that <a target="_blank" href="https://github.com/expo/router/discussions/1">here</a></p>
</blockquote>
<h2 id="heading-the-new-architecture">The new Architecture 📐</h2>
<p>The current Architecture of React Native is released officially with rn <code>--v 0.69</code>
and it has JSI mechanism which allows a JavaScript object to hold a reference to a C++ and vice-versa.
Several advantages of the new Architecture can be read <a target="_blank" href="https://reactnative.dev/docs/next/the-new-architecture/why#new-architectures-improvements">here</a>
<img src="https://www.freecodecamp.org/news/content/images/2022/09/glpaukHV4.png" alt="glpaukHV4" /></p>
<h2 id="heading-runtime-engine">Runtime engine 🏎️</h2>
<p>Web developers are well aware about the V8 engine that takes our javascript and execute it in the browser and node js. It provides the runtime environment in which javascript executes. The DOM, and the other Web Platform APIs are provided by the browser.
And in case of mobile development with reactnative, there is this Hermes engine, which  is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode.
<img src="https://www.freecodecamp.org/news/content/images/2022/09/HermesOSSChainReact_blog_FIN_1-1.gif" alt="HermesOSSChainReact_blog_FIN_1-1" />
what happens is it bundles the overall code of reactnative apps with whatever native modules are used in the code are compiled ahead of the time because of present JSI structure architecture. As there is no lag that was there in sending and getting message across the bridge. This results in faster initial load-up of reactnative apps. <a target="_blank" href="https://engineering.fb.com/2018/11/02/web/react-conf/">Image Ref</a></p>
<h2 id="heading-renderer">Renderer🖌️🎨</h2>
<p>A renderer teaches React to talk to a specific host environment and manage its host instances. You learn more upon it <a target="_blank" href="https://overreacted.io/react-as-a-ui-runtime/">here</a></p>
<h2 id="heading-fabric-renderer">Fabric Renderer</h2>
<p>The Fabric Renderer exists in JavaScript and targets interfaces made available by C++ code.
I see Fabric as an effort aimed to modernize the rendering layer of React Native. Fabric relies on some new strategies, such as:</p>
<ul>
<li>Using C++ for cross-platform "shadow" layer;</li>
<li>Immutable data structures (Shadow Trees, Props, Events);</li>
<li>Shared memory ownership (between JS and native);</li>
<li>JSI as an interop layer between JavaScript and native;</li>
<li>Type-safe data structures;</li>
<li>Opt-in synchronous execution where it benefits performance, the UI responsiveness 
 and simplifying inherently-synchronous interop APIs.</li>
<li>Fabric is all about modern, easy-to-interop and performant UI</li>
</ul>
<p>Resource: <a target="_blank" href="https://github.com/react-native-community/discussions-and-proposals/issues/4">https://github.com/react-native-community/discussions-and-proposals/issues/4</a></p>
<h2 id="heading-jsi">JSI ↔️</h2>
<p>Architecture inspired from web , as in web the modules are native to OS you are developing upon, we just access them wth javascript from browsers</p>
<p>JSI is not a part of React Native, it's a unified lightweight general purpose API for (theoretically) any JavaScript virtual machine. Now there is only one implementation of that - for JavaScriptCore VM.</p>
<p>JSI has/allows:</p>
<ul>
<li><p>Expose some native objects as JS objects and vice-versa;</p>
</li>
<li><p>Expose API for synchronous calling on this object in both directions.</p>
</li>
<li><p>Everything else should be built on top of that.</p>
</li>
</ul>
<p>Resource:<a target="_blank" href="https://github.com/react-native-community/discussions-and-proposals/issues/4#issue-346233667">https://github.com/react-native-community/discussions-and-proposals/issues/4#issue-346233667</a></p>
<h2 id="heading-turbo-modules">Turbo Modules</h2>
<p>Advanced native modules accessible to non native language that is javascipt, because of the JSI architecture  are now easy to hookup with new variations and manipulate with 
the common shadow tree generated in react native that resemble different native modules of android and iOS written in different languages like Java and Swift respectively</p>
<p>Over on twitter, @ericlewis published a sample repo with @chrfalch to showcase how to use directly C++ in a RN app (thanks to the JSI): https://github.com/ericlewis/react-native-hostobject-demo on <a target="_blank" href="https://github.com/react-native-community/discussions-and-proposals/issues/91">https://github.com/react-native-community/discussions-and-proposals/issues/91</a></p>
<h2 id="heading-codegen">codeGen</h2>
<p>JSI establishes interaction between JS and C++, but javascript is a dynamically typed language and C++ is a statically typed language, so codegen will auto-generate a statically typed boilerplate, incase anyone write native code with typescript.  </p>
<p>There’s a background process in the JavaScript engine that is called garbage collector. It monitors all objects and removes those that have become unreachable or inaccessible. <a target="_blank" href="https://javascript.info/garbage-collection">https://javascript.info/garbage-collection</a></p>
<h2 id="heading-devtools">DevTools🛠️</h2>
<p>Web developers use Chrome Developer Tools while developing web apps to debug their application. React Native also lets developers debug with the same Chrome Dev Tools, with an option  of <code>Debug JS Remotely</code> and integrated Inspector from developer menu of the app. 
You can read more about debugging in react native <a target="_blank" href="https://reactnative.dev/docs/debugging">here</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/inspector-4bd1342086bcd964bbd7f82e453743a7-1.gif" alt="inspector-4bd1342086bcd964bbd7f82e453743a7-1" /></p>
<h2 id="heading-package-culture">Package Culture</h2>
<p>Web Developers are well aware and suited with the use of node modules and a marketplace for modules is npmjs.com . React Native Developers broadly uses<br />packages and modules from that same marketplace. These packages are built natively using JSI in C++ or Java (native code) . You can watch <a target="_blank" href="https://www.youtube.com/watch?v=foEacW-Ze3w">this video</a> for better clarity.</p>
<blockquote>
<p>Documentation updated [https://reactnative.dev/docs/native-components-android]
(https://reactnative.dev/docs/native-components-android)</p>
</blockquote>
<h3 id="heading-from-here">From here: 🌼</h3>
<p>The web developers can easily switch/shift to mobile development. Hope this guide helps them understand the subtle differences. You can <a target="_blank" href="https://tech-blog.agrittiwari.com/getting-started-with-react-native">get started with React Native</a> easily.</p>
<p>References:</p>
<ul>
<li>https://reactnative.dev/docs</li>
<li>Github Issue Comments</li>
</ul>
<h3 id="heading-newsletter">Newsletter 🌟</h3>
<p>If you like the following blog, consider signing up for my newsletter, where I monthly share nuggets and my learnings about React Native and Next.js World for the community</p>
<h2 id="heading-httpswwwgetrevuecoprofileagrittiwarihttpswwwgetrevuecoprofileagrittiwari"><a target="_blank" href="https://www.getrevue.co/profile/agrit_tiwari">https://www.getrevue.co/profile/agrit_tiwari</a></h2>
<p><iframe src="https://giphy.com/embed/7vfhdCIn13zm8" width="480" height="288" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/vintage-opening-7vfhdCIn13zm8">via GIPHY</a></p><p></p>
]]></content:encoded></item><item><title><![CDATA[Planetscale DB and NextAuth.js starter for full stack applications]]></title><description><![CDATA[😃Hello !
The world is already full of news and chaos and we rarely found joyful news, then it is better to reflect back on the joyful and funny memories and experience. What is better than sharing the funny incidents and laughter with the world and ...]]></description><link>https://tech-blog.agrittiwari.com/nextauth-planetscale-starter</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/nextauth-planetscale-starter</guid><category><![CDATA[PlanetScaleHackathon]]></category><category><![CDATA[PlanetScale]]></category><category><![CDATA[nextauth.js]]></category><category><![CDATA[starter]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Sun, 31 Jul 2022 09:00:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659255447018/t-DsKXayn.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-hello">😃Hello !</h1>
<p>The world is already full of news and chaos and we rarely found joyful news, then it is better to reflect back on the joyful and funny memories and experience. What is better than sharing the funny incidents and laughter with the world and make this a better place to live in. Read and share your funny incidents, and experiences on <a target="_blank" href="https://funny-incidents.vercel.app">funny-incidents</a>⛷️⛷️⛷️</p>
<p>You can checkout this app and contribute fun and joy to the world or just enjoy some entries. <a target="_blank" href="https://nextjs-planetscale-nextauth-starter.vercel.app/">HostedLink</a> and <a target="_blank" href="https://github.com/agrittiwari/nextjs-planetscale-nextAuth-starter">RepoLink</a></p>
<p>With the growing popularity of <a target="_blank" href="https://app.planetscale.com/">PlanetScale</a> database, and my love for <a target="_blank" href>NextJS</a> and <a target="_blank" href="https://github.com/nextauthjs">Next-Auth.js</a>, I am more than motivated to build a full fledged appplication starter project with planetscale DB and nextauth as my tech stack. </p>
<h1 id="heading-focus">🎯Focus</h1>
<blockquote>
<p>We are focusing to building a starter project with nextAuth integration to Planetscale database. We added the concept of funny incidents as an example of what can be made out of this starter. Now this starter takes care of Auth with smooth developer experience we had with Planetscale db. The standard aspects of any project is covered with this starter stack , i.e. <strong>NextJS, NextAuth and Planetscale DB</strong></p>
<p><iframe src="https://giphy.com/embed/TDdExacavCVvq" width="480" height="480" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/art-motion-arte-TDdExacavCVvq">via GIPHY</a></p><p></p>
</blockquote>
<h1 id="heading-usage">💎Usage</h1>
<p>You can for the <a target="_blank" href="https://www.github.com/agrittiwari/nextjs-planetscale-nextAuth-starter">repo</a> and make your full fledged applications</p>
<h1 id="heading-pre-requisites">🎒 Pre-requisites</h1>
<p>It is an advance tutorial and expect you to have basic knowledge about some concepts, launguage and tech stack, like;</p>
<ul>
<li>Javascript</li>
<li>CSS</li>
<li>NodeJS ( <a target="_blank" href="https://nodejs.org/en/download/">install</a>)</li>
<li>NextJS</li>
<li>PlanetScale (<a target="_blank" href="https://github.com/planetscale/cli">install from here</a>)</li>
<li>SQL database</li>
<li>Basics of authZ and authN</li>
</ul>
<h1 id="heading-setup">🛠️ Setup</h1>
<p>To begin setting up the project, open a folder to directory you like in the editor and console.
Write the following command to setup the project </p>
<pre><code>npx <span class="hljs-keyword">create</span>-<span class="hljs-keyword">next</span>-app projectName
</code></pre><p>After moving to project directory <code>cd projectName</code> , install these packages via CLI </p>
<pre><code>npm install next<span class="hljs-operator">-</span>auth @prisma<span class="hljs-operator">/</span>client @next<span class="hljs-operator">-</span>auth<span class="hljs-operator">/</span>prisma<span class="hljs-operator">-</span>adapter
npm install <span class="hljs-operator">-</span>g prisma
</code></pre><h1 id="heading-setting-up-nextauth-and-planetscale-with-prisma">Setting up NextAuth 👤and PlanetScale with Prisma</h1>
<h2 id="heading-planetscale">PlanetScale🧰</h2>
<p>As I am a windows user and wanted to experience <code>Planetscale CLI</code>, I had to install <code>scoop</code> to run planetscale cli. Follow <a target="_blank" href="https://github.com/ScoopInstaller/Install/blob/master/README.md">here</a>.</p>
<ul>
<li>Set up the <a target="_blank" href="https://auth.planetscale.com/sign-up">PlanetScale Account</a>🧰 and can create a new database from PlanetScale Dashboard</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658557403598/7YjbQq6lr.png" alt="create-database.png" />
 Follow up on <code>PlanetScale CLI</code> usage <a target="_blank" href="https://docs.planetscale.com/docs/tutorials/planetscale-quick-start-guide#sign-in-to-your-account">here</a> </p>
<h3 id="heading-generate-a-connection-string">Generate a connection string</h3>
<p><iframe src="https://giphy.com/embed/6AnNiWdAWRkFrYWg0O" width="480" height="320" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/6AnNiWdAWRkFrYWg0O">via GIPHY</a></p>
In your PlanetScale dashboard, select your database, click "Connect", and select "Node.js" from the "Connect with" dropdown.<p></p>
<p>Copy the <code>DATABASE_URL</code> string from the <code>.env</code> tab and paste it into your own <code>.env</code>file. The structure will look like this:</p>
<pre><code>DATABASE_URL='mysql://<span class="hljs-tag">&lt;<span class="hljs-name">USERNAME</span>&gt;</span>:<span class="hljs-tag">&lt;<span class="hljs-name">PASSWORD</span>&gt;</span>@<span class="hljs-tag">&lt;<span class="hljs-name">HOST</span>&gt;</span>/<span class="hljs-tag">&lt;<span class="hljs-name">DATABASE_NAME</span>&gt;</span>?ssl={"rejectUnauthorized":true}'
</code></pre><blockquote>
<p>NextAuth is an open-source library that provides authentication authorisation support. It provides various providers like <code>google</code>,<code>facebook</code>, <code>apple</code>, <code>discord</code>, etc for auth and
many adapters are integrated like <code>Firebase</code>,<code>MongoDB</code>,<code>FaunaDB</code>,<code>DynamoDB</code>,<code>Prisma</code>,etc.</p>
<p>NextAuth provides hooks like <code>useSession</code>  to be used at component and page level. It is very simple to integrate functionality like login and logout as NextAuth takes care all of the functionality related to jwt, refreshToken and accessToken.</p>
</blockquote>
<h2 id="heading-nextauth">NextAuth 🔐</h2>
<p>To be able to use <code>useSession</code> first you'll need to expose the session context, <code>&lt;SessionProvider /&gt;</code>, at the top level of your application:</p>
<pre><code>pages<span class="hljs-operator">/</span>_app.js
<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'../styles/globals.css'</span>;

<span class="hljs-keyword">import</span> { <span class="hljs-title">SessionProvider</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"next-auth/react"</span>
<span class="hljs-title">export</span> <span class="hljs-title">default</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">App</span>({
  <span class="hljs-title">Component</span>,
  <span class="hljs-title">pageProps</span>: { <span class="hljs-title">session</span>, ...<span class="hljs-title">pageProps</span> },
}) {
  <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
    <span class="hljs-operator">&lt;</span><span class="hljs-title">SessionProvider</span> <span class="hljs-title">session</span><span class="hljs-operator">=</span>{<span class="hljs-title">session</span>}<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">Component</span> {...<span class="hljs-title">pageProps</span>} <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">SessionProvider</span><span class="hljs-operator">&gt;</span>
  )
}
</code></pre><p>Create a file called <code>[...nextauth].js</code> in <code>pages/api/auth</code>.  And write the following code:</p>
<pre><code><span class="hljs-keyword">import</span> NextAuth <span class="hljs-keyword">from</span> <span class="hljs-string">"next-auth"</span>
<span class="hljs-keyword">import</span> GoogleProvider <span class="hljs-keyword">from</span> <span class="hljs-string">'next-auth/providers/google'</span>
<span class="hljs-keyword">import</span> { PrismaAdapter } <span class="hljs-keyword">from</span> <span class="hljs-string">"@next-auth/prisma-adapter"</span>
<span class="hljs-keyword">import</span> prisma <span class="hljs-keyword">from</span> <span class="hljs-string">'../../../lib/prisma'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NextAuth({
  <span class="hljs-attr">adapter</span>: PrismaAdapter(prisma),
  <span class="hljs-comment">// Configure one or more authentication providers</span>
  <span class="hljs-attr">providers</span>: [
    GoogleProvider({
      <span class="hljs-attr">clientId</span>: process.env.GOOGLE_CLIENT_ID,
      <span class="hljs-attr">clientSecret</span>: process.env.GOOGLE_cLIENT_SECRET,
    }),
    <span class="hljs-comment">// ...add more providers here</span>
  ],
})
</code></pre><p>As you can clearly see, the provider used is <code>Google</code>, so you need CLIENT_ID and CLIENT_SECRET, which you can retreive from <a target="_blank" href="https://console.cloud.google.com/">here</a>. You can follow <a target="_blank" href="https://www.youtube.com/watch?v=xH6hAW3EqLk&amp;ab_channel=CodeJava">this</a> guide to obtain credentials and paste them in <code>/.env</code> file under root project directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658493708331/0Veq4KyKj.png" alt="console google.png" /></p>
<h2 id="heading-connecting-prisma-to-planetscale-and-designing-schema-for-nextauth">Connecting Prisma to PlanetScale and designing Schema for NextAuth</h2>
<p><iframe src="https://giphy.com/embed/UIUaD8DbQm2NIFU771" width="480" height="259" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/clashroyale-goblin-clash-royale-supercell-UIUaD8DbQm2NIFU771">via GIPHY</a></p><p></p>
<p>Create a file <code>prisma.js</code> under <code>/lib</code> folder in root directory and paste the following code:</p>
<pre><code><span class="hljs-keyword">import</span> { <span class="hljs-title">PrismaClient</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'@prisma/client'</span>;

let prisma;

<span class="hljs-keyword">if</span> (process.env.NODE_ENV <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'production'</span>) {
  prisma <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> PrismaClient();
} <span class="hljs-keyword">else</span> {
  <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>global.prisma) {
    global.prisma <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> PrismaClient();
  }
  prisma <span class="hljs-operator">=</span> global.prisma;
}

export default prisma;
</code></pre><blockquote>
<p><a target="_blank" href="https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#prevent-hot-reloading-from-creating-new-instances-of-prismaclient">Referenced from official docs</a> :  Frameworks like Next.js support hot reloading of changed files, which enables you to see changes to your application without restarting. However, if the framework refreshes the module responsible for exporting PrismaClient, this can result in additional, unwanted instances of PrismaClient in a development environment.</p>
<p>As a workaround, you can store PrismaClient as a global variable in development environments only, as global variables are not reloaded:</p>
</blockquote>
<p>Now,  invoke prisma in your application;</p>
<pre><code>npx prisma <span class="hljs-keyword">init</span>
</code></pre><p>This command does two things: (<a target="_blank" href="https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-planetscale">referenced from here</a>)</p>
<ul>
<li><p>creates a new directory called prisma that contains a file called schema.prisma, which contains the Prisma schema with your database connection variable and schema models</p>
</li>
<li><p>creates the .env file in the root directory of the project, which is used for defining environment variables (such as your database connection)</p>
</li>
</ul>
<p>Paste the following code in file <code>schema.Prisma</code></p>
<pre><code>generator client {
  provider        = <span class="hljs-string">"prisma-client-js"</span>
  previewFeatures = [<span class="hljs-string">"referentialIntegrity"</span>]
}

datasource db {
  provider             = <span class="hljs-string">"mysql"</span>
  url                  = env(<span class="hljs-string">"PLANETSCALE_PRISMA_DATABASE_URL"</span>)
  referentialIntegrity = <span class="hljs-string">"prisma"</span>
}

model Account {
  id                <span class="hljs-built_in">String</span>  <span class="hljs-meta">@id</span> <span class="hljs-meta">@default</span>(cuid())
  userId            <span class="hljs-built_in">String</span>
  type              <span class="hljs-built_in">String</span>
  provider          <span class="hljs-built_in">String</span>
  providerAccountId <span class="hljs-built_in">String</span>
  refresh_token     <span class="hljs-built_in">String?</span> <span class="hljs-meta">@db</span>.Text
  access_token      <span class="hljs-built_in">String?</span> <span class="hljs-meta">@db</span>.Text
  expires_at        Int?
  token_type        <span class="hljs-built_in">String?</span>
  scope             <span class="hljs-built_in">String?</span>
  id_token          <span class="hljs-built_in">String?</span> <span class="hljs-meta">@db</span>.Text
  session_state     <span class="hljs-built_in">String?</span>

  user User <span class="hljs-meta">@relation</span>(fields: [userId], references: [id], onDelete: Cascade)

  @<span class="hljs-meta">@unique</span>([provider, providerAccountId])
}

model Session {
  id           <span class="hljs-built_in">String</span>   <span class="hljs-meta">@id</span> <span class="hljs-meta">@default</span>(cuid())
  sessionToken <span class="hljs-built_in">String</span>   <span class="hljs-meta">@unique</span>
  userId       <span class="hljs-built_in">String</span>
  expires      <span class="hljs-built_in">DateTime</span>
  user         User     <span class="hljs-meta">@relation</span>(fields: [userId], references: [id], onDelete: Cascade)
}

model User {
  id            <span class="hljs-built_in">String</span>     <span class="hljs-meta">@id</span> <span class="hljs-meta">@default</span>(cuid())
  name          <span class="hljs-built_in">String?</span>
  email         <span class="hljs-built_in">String?</span>    <span class="hljs-meta">@unique</span>
  emailVerified <span class="hljs-built_in">DateTime?</span>
  image         <span class="hljs-built_in">String?</span>
  accounts      Account[]
  sessions      Session[]
  incidents     Incident[]
}

model VerificationToken {
  identifier <span class="hljs-built_in">String</span>
  token      <span class="hljs-built_in">String</span>   <span class="hljs-meta">@unique</span>
  expires    <span class="hljs-built_in">DateTime</span>

  @<span class="hljs-meta">@unique</span>([identifier, token])
}

model Incident {
  id        Int      <span class="hljs-meta">@id</span> <span class="hljs-meta">@default</span>(autoincrement())
  event     <span class="hljs-built_in">String</span>   <span class="hljs-meta">@db</span>.Text()
  createdAt <span class="hljs-built_in">DateTime</span> <span class="hljs-meta">@default</span>(now())
  yearsAgo  Int
  country   <span class="hljs-built_in">String</span>
  user      User?    <span class="hljs-meta">@relation</span>(fields: [authorId], references: [id])
  authorId  <span class="hljs-built_in">String?</span>

  @<span class="hljs-meta">@index</span>([authorId])
}
</code></pre><p>Run the following command to generate prisma client  and re-run whenever your model changes in <code>schema.prisma</code> file</p>
<pre><code><span class="hljs-attribute">prisma</span> generate
</code></pre><p>You can see the prisma client generation graphically from this image, taken from <a target="_blank" href="https://www.prisma.io/docs/getting-started">official docs</a></p>
<blockquote>
<p>💡 Debug type errors for your failing model in <code>schema.prisma</code> file. You can check and update your types mapped to Prisma with respect to MySql <a target="_blank" href="https://www.prisma.io/docs/concepts/database-connectors/mysql#native-type-mappings">here</a></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658556240735/9IkHOq4mp.png" alt="On prisma schema change.png" /></p>
<h2 id="heading-populate-the-planescale-database-with-updated-schema">Populate the Planescale Database with updated Schema</h2>
<p>With the database connected, you have to push the schema to your <code>PlanetScale Database</code> to perform read/write operation with Prisma client. Execute the following command:</p>
<pre><code>npx prisma db <span class="hljs-keyword">push</span>
</code></pre><blockquote>
<p><code>prisma db push</code>  uses the same engine as Prisma Migrate to synchronize your Prisma schema with your database schema. The db push command:</p>
<p>Introspects the database to infer and executes the changes required to make your database schema reflect the state of your Prisma schema.</p>
<p>By default, after changes have been applied to the database schema, generators are triggered (for example, Prisma Client). You do not need to manually invoke prisma generate.
<a target="_blank" href="https://www.prisma.io/docs/concepts/components/prisma-migrate/db-push">from official docs</a></p>
</blockquote>
<p>Dashboard will be like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658579080054/Jc10yMtOa.png" alt="dashboard PlanetScale 1.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658579086073/RF0ftCNlC.png" alt="dashboard PlanetScale 2.png" /></p>
<h3 id="heading-use-prisma-client-to-send-queries-to-your-planetscale-database">Use Prisma Client to send queries to your PlanetScale database</h3>
<p>Prisma client is used on the server side not browser side, so the following code takes care of <code>GET</code> and <code>POST</code> requests method on the file <code>/api/addIncident/index.js</code></p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">prisma</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../../../lib/prisma"</span>;

export default async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">if</span> (req.method <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"POST"</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">return</span> await addIncident(req, res);
    } <span class="hljs-keyword">catch</span> (err) {
      console.error(err);
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-built_in">msg</span>: <span class="hljs-string">"Something went wrong"</span> });
    }
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (req.method <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">"GET"</span>) {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">return</span> await getIncident(req, res);
    } <span class="hljs-keyword">catch</span> (err) {
      console.error(err);
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-built_in">msg</span>: <span class="hljs-string">"Something went wrong"</span> });
    }
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">405</span>).json({ <span class="hljs-built_in">msg</span>: <span class="hljs-string">"Method not allowed"</span> });
  }
}

<span class="hljs-comment">//-------GET THE INCIDENTS DATA FROM DB-------//</span>
const getIncident <span class="hljs-operator">=</span> async (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  <span class="hljs-keyword">try</span> {
    const incidents <span class="hljs-operator">=</span> await prisma.incident.findMany({
      include: {
        user: <span class="hljs-literal">true</span>,
      },
    });
    <span class="hljs-keyword">return</span> res
      .status(<span class="hljs-number">200</span>)
      .json({ incidents, success: <span class="hljs-string">"Successfully get the data"</span> });
  } <span class="hljs-keyword">catch</span> (err) {
    console.error(err);
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-built_in">msg</span>: <span class="hljs-string">"Something went wrong"</span> });
  }
};

<span class="hljs-comment">//--------ADD DATA TO TH DB OF INCIDENTS DETAILS--------//</span>
const addIncident <span class="hljs-operator">=</span> async (req, res) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  <span class="hljs-keyword">try</span> {
    const { <span class="hljs-function"><span class="hljs-keyword">event</span>, <span class="hljs-title">yearsAgo</span>, <span class="hljs-title">country</span>, <span class="hljs-title">authorId</span> } = <span class="hljs-title">req</span>.<span class="hljs-title">body</span></span>;
    const incident <span class="hljs-operator">=</span> await prisma.incident.create({
      data: {
        <span class="hljs-function"><span class="hljs-keyword">event</span>,
        <span class="hljs-title">yearsAgo</span>,
        <span class="hljs-title">country</span>,
        <span class="hljs-title">authorId</span>,
      },
    })</span>;
    <span class="hljs-keyword">return</span> res
      .status(<span class="hljs-number">200</span>)
      .json({ incident, <span class="hljs-built_in">msg</span>: <span class="hljs-string">"Incident added succesfully"</span> });
  } <span class="hljs-keyword">catch</span> (err) {
    console.error(err);
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-built_in">msg</span>: <span class="hljs-string">"Something went wrong"</span> });
  }
};
</code></pre><h1 id="heading-why-planetscale">Why PlanetScale💻</h1>
<p>I didn't knew MySQL database prior to this hackathon, but Planetscale has the best learning dashboard for a cloud db</p>
<ul>
<li>Smooth Developer experience</li>
<li>Room for error and debugging with it branching capabilities</li>
<li>Console at dashboard, I wrote many queries there and it's smooth</li>
<li>Schema UI , simply awesome.
I am very interested in learning and building apps with relational database, because of Planetscale DB.🥳🥳
<iframe src="https://giphy.com/embed/SGZcrHnUMbl7WPJFMV" width="480" height="479" class="giphy-embed"></iframe><p><a href="https://giphy.com/gifs/cbs-kids-say-the-darndest-things-darnedest-season-2-SGZcrHnUMbl7WPJFMV">via GIPHY</a></p> </li>
</ul>
<h2 id="heading-important-links">Important Links</h2>
<h3 id="heading-ui-code">UI code</h3>
<p>You can trace the UI code from the following link and visualise the UI as well:</p>
<ul>
<li><a target="_blank" href>Github Link</a></li>
<li><a target="_blank" href="https://nextjs-planetscale-nextauth-starter.vercel.app/">Funny-incidents/Planetscale-nextauth-starter</a></li>
</ul>
<h1 id="heading-deployment-to-vercel">🧑‍🚀Deployment to Vercel</h1>
<p>To put the app in production, there are few thngs to take care of, these are:</p>
<blockquote>
<p>Do add all the domains from your vercel dashboards on <a target="_blank" href="https://console.cloud.google.com/">https://console.cloud.google.com/</a> to use nextAuth in production with Google as provider.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658819953265/gc-knCBwj.png" alt="nextAuth.png" /></p>
<h2 id="heading-add-the-environment-variables">Add the environment variables</h2>
<p>Add the following environvent variables, <code>NEXTAUTH_SECRET</code>,<code>GOOGLE_CLIENT_SECRET</code>,<code>GOOGLE_CLIENT_ID</code>, and <code>PLANETSCALE_PRISMA_DATABASE_URL</code> on the <a target="_blank" href="https://www.vercel.com">Vercel</a> project Dashboard
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658819246920/HIM3jmLms.png" alt="vercel environment variables.png" /></p>
<h1 id="heading-conclusion">🌼 Conclusion</h1>
<p>This project can act as a starter for nextAuth and Planetscale integration. The project itself is a happy place. Thank you for your time. </p>
<p><iframe src="https://giphy.com/embed/26FPOogenQv5eOZHO" width="480" height="346" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/larrysprings-26FPOogenQv5eOZHO">via GIPHY</a></p><p></p>
]]></content:encoded></item><item><title><![CDATA[Migrating to Reactnative version 0.69 (part 1)]]></title><description><![CDATA[Hello all !,
React Native has rollout the new architecture as default from version 0.68. And the following path of the react native community will be focused on the new architecture, the debugging support, library supports, etc. This has been another...]]></description><link>https://tech-blog.agrittiwari.com/migrating-to-reactnative-version-069-part-1</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/migrating-to-reactnative-version-069-part-1</guid><category><![CDATA[React Native]]></category><category><![CDATA[0.69]]></category><category><![CDATA[buildFails]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Tue, 26 Jul 2022 15:34:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658849464923/DnwYc5boB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello all !,
React Native has rollout the new architecture as default from version 0.68. And the following path of the react native community will be focused on the new architecture, the debugging support, library supports, etc. This has been another reason to migrate to new architecture, ofcourse the JSI based architecture (new architecture) has many advantages over the bridge based architecture.</p>
<p>Migrating a large codebase is an opportunity to learn about a lot of useful libraries and even refreshing the fundamentals of operation once again.</p>
<p>So, the migration is happening all over the globe, you know, to the new architecture. We at my internship, were also inclined to migrate. And I, hereby wanted to note the migration journey for the community. </p>
<h1 id="heading-build-fails">Build Fails</h1>
<p>Build failed for the</p>
<blockquote>
<p>Task :app:checkDebugAarMetadata FAILED
```
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
updated the compiledSdkVersion and targetSdkVersion to 31 and also updated API version of virtual device to 31.</p>
</blockquote>
<p>React native adoption to JSI brought the C++/ Java interface close to javascript UI developer. Going to directory <code>android/ app /build.gradle</code> . Seeing the flag <code>enableHermes = false</code> as a default setting, it dawned on me to update the flag <code>enableHermes: true  // clean and rebuild if changing</code></p>
<pre><code><span class="hljs-attribute">FAILURE</span>: Build failed with an exception.

<span class="solidity"><span class="hljs-operator">*</span> What went wrong:
Execution failed <span class="hljs-keyword">for</span> task <span class="hljs-string">':react-native-screens:compileDebugKotlin'</span>.
&gt; Compilation <span class="hljs-keyword">error</span>. See log <span class="hljs-keyword">for</span> more details</span>
</code></pre><h2 id="heading-solution">Solution</h2>
<p>Installing Gradle on windows machine with manual <a target="_blank" href="https://gradle.org/">latest version released on July 14, 2022</a></p>
<pre><code>Welcome to Gradle <span class="hljs-number">7.5</span><span class="hljs-operator">!</span>

Here are the highlights of <span class="hljs-built_in">this</span> release:
 <span class="hljs-operator">-</span> Support <span class="hljs-keyword">for</span> Java <span class="hljs-number">18</span>
 <span class="hljs-operator">-</span> Support <span class="hljs-keyword">for</span> building with Groovy <span class="hljs-number">4</span>
 <span class="hljs-operator">-</span> Much more responsive continuous builds
 <span class="hljs-operator">-</span> Improved diagnostics <span class="hljs-keyword">for</span> dependency resolution
</code></pre><p>Following the official <a target="_blank" href="https://reactnative.dev/docs/new-architecture-app-intro#android-specifics">react native docs</a>, The <code>--distribution-type=all</code> tag is in difference with <code>--distribution-type=bin</code> tag on <a target="_blank" href="https://gradle.org/install/">gradle official docs</a> for installation.</p>
<p>*What Went wrong</p>
<blockquote>
<p>Could not resolve all files for configuration ':classpath'.
Could not download tink-1.3.0-rc2.jar (com.google.crypto.tink:tink:1.3.0-rc2)
Could not get resource 'https://jcenter.bintray.com/com/google/crypto/tink/tink/1.3.0-rc2/tink-1.3.0-rc2.jar'.
java.io.IOException: Data error (cyclic redundancy check)</p>
</blockquote>
<pre><code><span class="hljs-selector-tag">BUILD</span> <span class="hljs-selector-tag">FAILED</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">12s</span>

    <span class="hljs-selector-tag">at</span> <span class="hljs-selector-tag">makeError</span> (<span class="hljs-attribute">E</span>:\Work\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\execa\index.<span class="hljs-attribute">js</span>:<span class="hljs-number">174</span>:<span class="hljs-number">9</span>)
    <span class="hljs-selector-tag">at</span> <span class="hljs-selector-tag">E</span>:\<span class="hljs-selector-tag">Work</span>\<span class="hljs-selector-tag">april</span> <span class="hljs-selector-tag">10</span>\<span class="hljs-selector-tag">pb_userModule</span>\<span class="hljs-selector-tag">reactnative_ui</span>\<span class="hljs-selector-tag">node_modules</span>\<span class="hljs-selector-tag">execa</span>\<span class="hljs-selector-tag">index</span><span class="hljs-selector-class">.js</span><span class="hljs-selector-pseudo">:278</span><span class="hljs-selector-pseudo">:16</span>
    <span class="hljs-selector-tag">at</span> <span class="hljs-selector-tag">processTicksAndRejections</span> (<span class="hljs-attribute">node</span>:internal/process/<span class="hljs-attribute">task_queues</span>:<span class="hljs-number">96</span>:<span class="hljs-number">5</span>)
    <span class="hljs-selector-tag">at</span> <span class="hljs-selector-tag">async</span> <span class="hljs-selector-tag">runOnAllDevices</span> (<span class="hljs-attribute">E</span>:\Work\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\<span class="hljs-variable">@react-native-community</span>\cli-platform-android\build\commands\runAndroid\runOnAllDevices.<span class="hljs-attribute">js</span>:<span class="hljs-number">109</span>:<span class="hljs-number">5</span>)
 <span class="hljs-selector-tag">at</span> <span class="hljs-selector-tag">async</span> <span class="hljs-selector-tag">Command</span><span class="hljs-selector-class">.handleAction</span> (<span class="hljs-attribute">E</span>:\Work\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\<span class="hljs-variable">@react-native-community</span>\cli\build\index.<span class="hljs-attribute">js</span>:<span class="hljs-number">192</span>:<span class="hljs-number">9</span>)
</code></pre><p>Solution: 
 Added <code>mavenlocal</code> in the top-level build.gradle file <a target="_blank" href="https://stackoverflow.com/questions/69205327/could-not-resolve-com-google-guavaguava30-1-jre-gradle-project-sync-failed">ref</a></p>
<pre><code> <span class="hljs-selector-tag">repositories</span> {
        <span class="hljs-selector-tag">mavenCentral</span>() <span class="hljs-comment">//added this line to solve classPath bug </span>
        <span class="hljs-selector-tag">google</span>()
        <span class="hljs-selector-tag">jcenter</span>()
    }
</code></pre><p>But this lead to another bug</p>
<pre><code>* <span class="hljs-type">What</span> went wrong:
<span class="hljs-type">A</span> problem occurred configuring root project <span class="hljs-symbol">'xyz</span>.
&gt; <span class="hljs-type">Failed</span> to create <span class="hljs-type">MD5</span> hash <span class="hljs-keyword">for</span> file content.

* <span class="hljs-type">Try</span>:
&gt; <span class="hljs-type">Run</span> <span class="hljs-keyword">with</span> --stacktrace option to get the stack trace.
&gt; <span class="hljs-type">Run</span> <span class="hljs-keyword">with</span> --info or --debug option to get more log output.
&gt; <span class="hljs-type">Run</span> <span class="hljs-keyword">with</span> --scan to get full insights.

* <span class="hljs-type">Get</span> more help at https:<span class="hljs-comment">//help.gradle.org</span>

<span class="hljs-type">BUILD</span> <span class="hljs-type">FAILED</span> in <span class="hljs-number">14</span>s

    at makeError (<span class="hljs-type">E</span>:\<span class="hljs-type">Work</span>\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\execa\index.js:<span class="hljs-number">174</span>:<span class="hljs-number">9</span>)
    at <span class="hljs-type">E</span>:\<span class="hljs-type">Work</span>\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\execa\index.js:<span class="hljs-number">278</span>:<span class="hljs-number">16</span>
    at processTicksAndRejections (node:internal/process/task_queues:<span class="hljs-number">96</span>:<span class="hljs-number">5</span>)
    at async runOnAllDevices (<span class="hljs-type">E</span>:\<span class="hljs-type">Work</span>\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\<span class="hljs-meta">@react</span>-native-community\cli-platform-android\build\commands\runAndroid\runOnAllDevices.js:<span class="hljs-number">109</span>:<span class="hljs-number">5</span>)
    at async <span class="hljs-type">Command</span>.handleAction (<span class="hljs-type">E</span>:\<span class="hljs-type">Work</span>\april <span class="hljs-number">10</span>\pb_userModule\reactnative_ui\node_modules\<span class="hljs-meta">@react</span>-native-community\cli\build\index.js:<span class="hljs-number">192</span>:<span class="hljs-number">9</span>)
info <span class="hljs-type">Run</span> <span class="hljs-type">CLI</span> <span class="hljs-keyword">with</span> --verbose flag <span class="hljs-keyword">for</span> more details.
</code></pre><p>Solution: I uninstalled reactnative cli package which was installed globally( no idea about its impact)</p>
<h3 id="heading-httpsgithubcominvertasereact-native-gradle-plugin">https://github.com/invertase/react-native-gradle-plugin</h3>
<p>Can look into <a target="_blank" href="https://reactnative.dev/docs/hermes#confirming-hermes-is-in-use">this to confirm</a></p>
<h1 id="heading-with-respect-to-android">With respect to Android</h1>
<ul>
<li>Installed Codegen with <code>yarn add --dev react-native-codegen</code></li>
</ul>
<p>"The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets</p>
<ul>
<li>and bundleReleaseJsAndAssets" This react.gradle file is replaced by the <code>react-native-gradle-plugin</code></li>
</ul>
<pre><code>
<span class="hljs-bullet">*</span> Added <span class="hljs-code">`react-native-gradle-plugin' with `</span>yarn add --dev react-native-gradle-plugin`
Updated the setting.gradle file with
</code></pre><p>includeBuild('../node_modules/react-native-gradle-plugin')</p>
<p>include(":ReactAndroid")
project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')</p>
<pre><code>This [<span class="hljs-string">ReactAndroid</span>](<span class="hljs-link">https://github.com/facebook/react-native/blob/main/ReactAndroid/DevExperience.md</span>) project is the new build of reactnative for android, it uses react-native-gradle-plugin for all the java and kotlin logic that lived inside the react.gradle This helps React Native to build and compile native code/ C++ in the CMake.Android.mk files

<span class="hljs-bullet">*</span> Added <span class="hljs-code">```     // Add those lines
        classpath("com.facebook.react:react-native-gradle-plugin")
        classpath("de.undercouch:gradle-download-task:4.1.2")</span>
</code></pre><p>in the android/build.gradle directory in dependencies obejct  to provide the link to reactnative -gradle-plugin so that it can use it during build process.</p>
<ul>
<li>Added <code>apply plugin: "com.facebook.react"
// Add those lines as well
react {
  reactRoot = rootProject.file("../node_modules/react-native/")
  codegenDir = rootProject.file("../node_modules/react-native-codegen/")
}</code>
int he module level build.gradle file and Finally added <code>implementation project(":ReactAndroid")</code> under dependencies so that react-native uses source code from the ReactAndroid project. <a target="_blank" href="https://github.com/facebook/react-native/blob/main/ReactAndroid">Read here</a></li>
</ul>
<ul>
<li>Install the new Gradle plugin for new Architecture</li>
</ul>
<p>Ran the  following command </p>
<pre><code>npx react<span class="hljs-operator">-</span>native run<span class="hljs-operator">-</span>android
</code></pre><h1 id="heading-packages-out-of-date">Packages Out of Date</h1>
<ul>
<li><p>Evidently, React Native version 69 has  18.0.0 as mininmum version of react. The react 18.0.0 version has introduced many revolutionary changes and advanced support methods and hooks for better UI development access.</p>
</li>
<li><p>Following react, it was obvious for <a target="_blank" href>react-test-renderer</a>to break. Updating the architecture, I came to know alot about the code and portion of code I haven't worked upon. </p>
</li>
</ul>
<p>Essentially, this package makes it easy to grab a snapshot of the platform view hierarchy (similar to a DOM tree) rendered by a React DOM or React Native component without using a browser or jsdom.( definition copied from <a target="_blank" href="https://reactjs.org/docs/test-renderer.html">docs</a>)</p>
<ul>
<li><a target="_blank" href="https://react-query-v3.tanstack.com/react-native">React Query for React Native</a> is limited evolved as it is for react-web. Whatever be the reason, it broke with version 3.34.1 and now upgraded to version 3.39.2</li>
</ul>
<p>It is a library that simplifies the way we fetch, cache and synchronize data from a server. Basic react library is insufficient when requirements like caching, retries and deduping comes into picture. </p>
<ul>
<li><p>The wonderful library  <a target="_blank" href="https://www.npmjs.com/package/@react-native-async-storage/async-storage">react-native-async-storage/async-storage@"^1.15.11"</a> also breaks support for the new architecture. This package has latest release [version@"1.17.7"]</p>
</li>
<li><p>After seeing the breaking version compatibility of almost every package, I moved on to upgrade the all packages with <code>npm update</code></p>
<pre><code>
<span class="hljs-string">"dependencies"</span>: {
  <span class="hljs-string">"@azure/msal-browser"</span>: <span class="hljs-string">"^2.19.0"</span>,
  <span class="hljs-string">"@microsoft/microsoft-graph-client"</span>: <span class="hljs-string">"^3.0.1"</span>,
  <span class="hljs-string">"@react-native-async-storage/async-storage"</span>: <span class="hljs-string">"^1.17.7"</span>,
  <span class="hljs-string">"@react-native-community/clipboard"</span>: <span class="hljs-string">"^1.5.1"</span>,
  <span class="hljs-string">"@react-native-community/datetimepicker"</span>: <span class="hljs-string">"^3.5.2"</span>,
  <span class="hljs-string">"@react-native-community/geolocation"</span>: <span class="hljs-string">"^2.0.2"</span>,
  <span class="hljs-string">"@react-native-community/netinfo"</span>: <span class="hljs-string">"^7.1.7"</span>,
  <span class="hljs-string">"@react-native-community/viewpager"</span>: <span class="hljs-string">"^5.0.11"</span>,
  <span class="hljs-string">"@react-native-firebase/app"</span>: <span class="hljs-string">"^14.5.1"</span>,
  <span class="hljs-string">"@react-native-google-signin/google-signin"</span>: <span class="hljs-string">"^6.0.1"</span>,
  <span class="hljs-string">"@react-native-picker/picker"</span>: <span class="hljs-string">"^2.2.0"</span>,
  <span class="hljs-string">"@react-navigation/bottom-tabs"</span>: <span class="hljs-string">"^6.0.9"</span>,
  <span class="hljs-string">"@react-navigation/material-top-tabs"</span>: <span class="hljs-string">"^6.0.6"</span>,
  <span class="hljs-string">"@react-navigation/native"</span>: <span class="hljs-string">"^6.0.6"</span>,
  <span class="hljs-string">"@react-navigation/stack"</span>: <span class="hljs-string">"^6.0.11"</span>,
  <span class="hljs-string">"@twotalltotems/react-native-otp-input"</span>: <span class="hljs-string">"^1.3.11"</span>,
  <span class="hljs-string">"axios"</span>: <span class="hljs-string">"^0.21.4"</span>,
  <span class="hljs-string">"buffer"</span>: <span class="hljs-string">"^6.0.3"</span>,
  <span class="hljs-string">"d3-scale"</span>: <span class="hljs-string">"^4.0.2"</span>,
  <span class="hljs-string">"email-validator"</span>: <span class="hljs-string">"^2.0.4"</span>,
  <span class="hljs-string">"install"</span>: <span class="hljs-string">"^0.13.0"</span>,
  <span class="hljs-string">"lodash"</span>: <span class="hljs-string">"^4.17.21"</span>,
  <span class="hljs-string">"moment"</span>: <span class="hljs-string">"^2.29.1"</span>,
  <span class="hljs-string">"moment-timezone"</span>: <span class="hljs-string">"^0.5.34"</span>,
  <span class="hljs-string">"npm"</span>: <span class="hljs-string">"^7.24.2"</span>,
  <span class="hljs-string">"password-validator"</span>: <span class="hljs-string">"^5.2.1"</span>,
  <span class="hljs-string">"react"</span>: <span class="hljs-string">"18.0.0"</span>,
  <span class="hljs-string">"react-native"</span>: <span class="hljs-string">"0.69"</span>,
  <span class="hljs-string">"react-native-animatable"</span>: <span class="hljs-string">"^1.3.3"</span>,
  <span class="hljs-string">"react-native-app-auth"</span>: <span class="hljs-string">"^6.4.0"</span>,
  <span class="hljs-string">"react-native-calendars"</span>: <span class="hljs-string">"^1.1268.0"</span>,
  <span class="hljs-string">"react-native-contacts"</span>: <span class="hljs-string">"^7.0.2"</span>,
  <span class="hljs-string">"react-native-countdown-component"</span>: <span class="hljs-string">"^2.7.1"</span>,
  <span class="hljs-string">"react-native-date-picker"</span>: <span class="hljs-string">"^4.1.1"</span>,
  <span class="hljs-string">"react-native-dropdown-picker"</span>: <span class="hljs-string">"^5.2.3"</span>,
  <span class="hljs-string">"react-native-email-link"</span>: <span class="hljs-string">"^1.12.2"</span>,
  <span class="hljs-string">"react-native-geocoder"</span>: <span class="hljs-string">"^0.5.0"</span>,
  <span class="hljs-string">"react-native-gesture-handler"</span>: <span class="hljs-string">"^1.10.3"</span>,
  <span class="hljs-string">"react-native-google-places-autocomplete"</span>: <span class="hljs-string">"^2.4.1"</span>,
  <span class="hljs-string">"react-native-linear-gradient"</span>: <span class="hljs-string">"^2.5.6"</span>,
  <span class="hljs-string">"react-native-network-info"</span>: <span class="hljs-string">"^5.2.1"</span>,
  <span class="hljs-string">"react-native-numeric-input"</span>: <span class="hljs-string">"^1.9.0"</span>,
  <span class="hljs-string">"react-native-pager-view"</span>: <span class="hljs-string">"^5.4.9"</span>,
  <span class="hljs-string">"react-native-picker-scrollview"</span>: <span class="hljs-string">"^1.0.1"</span>,
  <span class="hljs-string">"react-native-popup-menu"</span>: <span class="hljs-string">"^0.15.11"</span>,
  <span class="hljs-string">"react-native-safe-area-context"</span>: <span class="hljs-string">"^3.3.2"</span>,
  <span class="hljs-string">"react-native-screens"</span>: <span class="hljs-string">"^3.9.0"</span>,
  <span class="hljs-string">"react-native-select-dropdown"</span>: <span class="hljs-string">"^2.0.4"</span>,

  <span class="hljs-string">"react-native-svg"</span>: <span class="hljs-string">"^12.1.1"</span>,
  <span class="hljs-string">"react-native-svg-charts"</span>: <span class="hljs-string">"^5.4.0"</span>,
  <span class="hljs-string">"react-native-tab-view"</span>: <span class="hljs-string">"^3.1.1"</span>,
  <span class="hljs-string">"react-native-vector-icons"</span>: <span class="hljs-string">"^8.1.0"</span>,
  <span class="hljs-string">"react-native-webview"</span>: <span class="hljs-string">"^11.15.0"</span>,
  <span class="hljs-string">"react-native-wheel-scroll-picker"</span>: <span class="hljs-string">"^0.2.4"</span>,
  <span class="hljs-string">"react-native-wheel-scrollview-picker"</span>: <span class="hljs-string">"^1.2.2"</span>,
  <span class="hljs-string">"react-query"</span>: <span class="hljs-string">"^3.39.2"</span>
},
<span class="hljs-string">"devDependencies"</span>: {
  <span class="hljs-string">"@babel/core"</span>: <span class="hljs-string">"7.15.0"</span>,
  <span class="hljs-string">"@babel/runtime"</span>: <span class="hljs-string">"7.15.3"</span>,
  <span class="hljs-string">"@react-native-community/eslint-config"</span>: <span class="hljs-string">"2.0.0"</span>,
  <span class="hljs-string">"babel-jest"</span>: <span class="hljs-string">"26.6.3"</span>,
  <span class="hljs-string">"eslint"</span>: <span class="hljs-string">"7.14.0"</span>,
  <span class="hljs-string">"jest"</span>: <span class="hljs-string">"26.6.3"</span>,
  <span class="hljs-string">"metro-react-native-babel-preset"</span>: <span class="hljs-string">"0.64.0"</span>,
  <span class="hljs-string">"react-native-svg-transformer"</span>: <span class="hljs-string">"^0.14.3"</span>,
  <span class="hljs-string">"react-test-renderer"</span>: <span class="hljs-string">"18.0.0"</span>
},
<span class="hljs-string">"jest"</span>: {
  <span class="hljs-string">"preset"</span>: <span class="hljs-string">"react-native"</span>
}
}
</code></pre></li>
<li><p>The command failed with error on <a target="_blank" href="https://www.npmjs.com/package/@react-native-picker/picker">react-native-picker/picker</a> package </p>
<pre><code>npm ERR<span class="hljs-operator">!</span> Could not resolve dependency:
npm ERR<span class="hljs-operator">!</span> peer react@<span class="hljs-string">"16 || 17"</span> <span class="hljs-keyword">from</span> @react<span class="hljs-operator">-</span>native<span class="hljs-operator">-</span>picker<span class="hljs-operator">/</span>picker@<span class="hljs-number">2.4</span><span class="hljs-number">.2</span>
</code></pre></li>
</ul>
<p>This error shows that certain packages are lacking compatibiltiy with reactnative version 0.69 .</p>
<ul>
<li><p>Package <a target="_blank" href="https://www.npmjs.com/package/react-native-numeric-input">react-native-numeric-input</a> just shown a dependency error of another package  react-native-vector-icons@"^8.1.0". </p>
</li>
<li><p>So, after updating the  <a target="_blank" href>react-native-vector-icons</a> to version 9.2.0 and removing the wro packages from codebase. command <code>npm i</code> ran without an error.</p>
</li>
</ul>
<ul>
<li>Launching my app with usual <code>react-native android</code> command for starting  after building.
<a target="_blank" href="https://www.npmjs.com/package/@react-native-google-signin/google-signin">react-native-google-signin/google-signin</a> package throws  a warning for invalid configuration <pre><code>"<span class="hljs-selector-tag">dependency</span><span class="hljs-selector-class">.platforms</span><span class="hljs-selector-class">.ios</span><span class="hljs-selector-class">.project</span>" <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">not</span> <span class="hljs-selector-tag">allowed</span>.
</code></pre>Again my package was outdated. Upgrade it to 8.0.0 version </li>
</ul>
<ul>
<li>Found another package <a target="_blank" href="https://www.npmjs.com/package/react-native-svg">react-native-svg</a>  which was to be updated from 12.1.1 to 12.4.0 but another package <a target="_blank" href="https://www.npmjs.com/package/react-native-svg-charts">react-native-svg-charts</a> dependent on lower versions of svg is out of date with new version of react-native-svg. Maintainers have not released a new version from last 2 years</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[NextJS and mongoDB application-v1]]></title><description><![CDATA[The basic functioning of any software company out there is to perform CRUD operations. The more they work on providing simplistic user Experience, the complexity grew under the hood. But the takeoff foundation remains simple, even for developers. 
Go...]]></description><link>https://tech-blog.agrittiwari.com/nextjs-and-mongodb-application-v1</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/nextjs-and-mongodb-application-v1</guid><category><![CDATA[THW Web Apps]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Vercel]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Sat, 30 Apr 2022 04:24:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651292166011/VZ9HcTR8-.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The basic functioning of any software company out there is to perform CRUD operations. The more they work on providing simplistic user Experience, the complexity grew under the hood. But the takeoff foundation remains simple, even for developers. </p>
<h1 id="heading-goal">Goal ⛰️🚵</h1>
<p>In this blog, we will build a full stack application using nextJS and mongoDB. Here is the product of our effort <a target="_blank" href="https://goals-of-our-generation.vercel.app/">https://goals-of-our-generation.vercel.app/</a>. 👈</p>
<p>This is the first blog of the series with minimal features. As the app evolves in further tutorials, there will be new functionalities and added complexity. We will explore many important functionalities of web ecosystem and there will a finished- working application with every blog.</p>
<h1 id="heading-pre-requisites">Pre-requisites ✋</h1>
<p>There are fair amount of pre-requisites to understand how this project is working, like:</p>
<ul>
<li><a target="_blank" href="https://javascript.info/">Understanding of Javascript</a></li>
<li><a target="_blank" href="https://beta.reactjs.org/">Basics of React and state management</a></li>
<li><a target="_blank" href="https://university.mongodb.com/">Basic knowledge of mongoDB</a>, the understanding of mongoDB will improve as project evolves</li>
<li><a target="_blank" href="https://www.nodejs.org">Node.js</a> installed. Node.js will help us run NPM commands to install any necessary dependencies that will help us build our Next.js application.</li>
<li>Since we are using <a target="_blank" href="https://nextjs.org/">NextJS</a>, prior experience/exposure to this framework will be helpful</li>
</ul>
<h1 id="heading-tech-stack">Tech Stack 🔧⚙️</h1>
<p><a target="_blank" href="https://nextjs.org/">NextJS</a> by <a target="_blank" href="https://vercel.com/">Vercel</a> has changed the way of developing web.</p>
<p>As we are going to use mongoDB, we can use template provided by Vercel  as <a target="_blank" href="https://github.com/vercel/next.js/tree/canary/examples/with-mongodb"><code>--with -mongodb</code></a> or we can begin with <code>npx create-next-app</code>. Example templates provide little boost in development, plus they are up-to-date with the methods/code used in setting up the connection with xyz(mongodb, in our case)</p>
<h1 id="heading-setting-up-mongodb-atlas-cluster">Setting up MongoDB Atlas Cluster</h1>
<p>To work with the template, we must have the uri string required to establish connection between our application and mongoDB atlas cluster. MongoDB Atlas is a cloud database service for MongoDB.
This means that you get to store and access your data from a remote computer. This eliminates the process of setting up MongoDB locally on your computer.</p>
<p>To use <a target="_blank" href="https://www.mongodb.com/cloud/atlas">MongoDB Atlas</a>, you need to have an account. If you don’t have one, create a free account. If already you have one, login from <a target="_blank" href="https://account.mongodb.com/account/login?nds=true">here</a>.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650960258679/PGkiNoY0N.png" alt="mongo createProject.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650960561242/cKj3bBXGW.png" alt="mongo clusterCreation.png" /></p>
<h3 id="heading-get-the-uri-string">Get the uri string</h3>
<p>Once you create an account, a project will be created and assigned a free MO Sandbox with a Shared cluster. Create user and password and add your device IP to access the cluster.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650960618100/7A7eUrcWI.png" alt="Connect to cluster.png" />
<em>Copy that connection String</em></p>
<h1 id="heading-setting-up-project">Setting up project</h1>
<p>To begin with, NextJS provide a command to build the scaffold of application and start development via starter templates and as we are using template for mongoDB integration. Create folder and change your directory to it and run this command</p>
<pre><code>npx create<span class="hljs-operator">-</span>next<span class="hljs-operator">-</span>app <span class="hljs-operator">-</span><span class="hljs-operator">-</span>example with<span class="hljs-operator">-</span>mongodb nextjs<span class="hljs-operator">-</span>mongodb<span class="hljs-operator">-</span>v1
</code></pre><p><code>nextjs-mongodb-v1</code> is the &lt; projectName &gt;. This will create the basic template. Now go to the directory by <code>cd nextjs-mongodb-v1</code>.</p>
<blockquote>
<p>Now add that connection string that you copied from mongo atlas dashboard in the env.local file by assigning it to variable MONGODB_URI and replace the  with your password</p>
</blockquote>
<p> and run <code>npm run dev</code>. This will start your development server in your local at <a target="_blank" href="http://localhost:300">port 3000</a> and if you can see this screen ⬇️, we are good to go.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650960906188/dy54Uj907.png" alt="nextJS+ MongoDB template.png" /></p>
<h1 id="heading-styling-via-tailwind-and-custom-css">Styling via Tailwind and custom CSS🕴️</h1>
<p>We need to provide styling, of course, to the application and Tailwind CSS works just fine along with nextJS. We can install tailwind in many ways, but using tailwind css CDN link works just fine for now. Copy the CDN link and paste it inside  of index.js. </p>
<p>Created a <a target="_blank" href="will create a link to this file">styles.css</a> at the root folder to import it inside the _app.js file. This _app.js file is created to pass down basic styling to all the components. This is _app.js file.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-string">'../styles.css'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span></span>
}
</code></pre><h1 id="heading-form-component">📝Form Component</h1>
<p>To perform CRUD operation, it is obvious that you need a form. Here is the code for the Form Component inside the directory <code>/Components/Form/index.js</code></p>
<pre><code><span class="hljs-keyword">import</span> { <span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"react"</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> { <span class="hljs-title">SuccessAlert</span>, <span class="hljs-title">ErrorAlert</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"../Alert"</span>;

 export const GoalForm <span class="hljs-operator">=</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
{ const [<span class="hljs-function"><span class="hljs-keyword">error</span>, <span class="hljs-title">setError</span>] = <span class="hljs-title">useState</span>(<span class="hljs-params"><span class="hljs-string">''</span></span>)</span>;
const [message, setMessage] <span class="hljs-operator">=</span> useState(<span class="hljs-string">''</span>);

const [name, setName] <span class="hljs-operator">=</span> useState(<span class="hljs-string">''</span>);
const [age, setAge] <span class="hljs-operator">=</span> useState(<span class="hljs-string">''</span>)
const [description, setDescription] <span class="hljs-operator">=</span> useState(<span class="hljs-string">''</span>)

const postGoal <span class="hljs-operator">=</span> async (e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
{
    e.preventDefault()

    setError(<span class="hljs-string">''</span>)
    setMessage(<span class="hljs-string">''</span>)

    <span class="hljs-keyword">if</span>(<span class="hljs-operator">!</span>name <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-operator">!</span>age <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-operator">!</span>description) <span class="hljs-keyword">return</span> setError(<span class="hljs-string">'All Fields are necessary!'</span>)
    let goal <span class="hljs-operator">=</span> {
        name,
        age,
       description,
        date:<span class="hljs-keyword">new</span> Date(),


}
    console.log(JSON.stringify(goal))
    console.log(goal)
    <span class="hljs-comment">//console.log(JSON.parse(details))</span>
    <span class="hljs-keyword">try</span> {
        const response <span class="hljs-operator">=</span> await fetch(<span class="hljs-string">'/api/goals'</span>, {
            method: <span class="hljs-string">'POST'</span>,
            body: JSON.stringify(goal)
        })

            <span class="hljs-comment">//get the data</span>

            let data <span class="hljs-operator">=</span> await response.json()
    console.log( `<span class="hljs-built_in">this</span> <span class="hljs-keyword">is</span> <span class="hljs-keyword">from</span> goal component ${data.message}`)
            <span class="hljs-keyword">if</span> (data.success) {
                 <span class="hljs-comment">// reset the fields</span>
                 setName(<span class="hljs-string">''</span>);
                setAge(<span class="hljs-string">''</span>);
                setDescription(<span class="hljs-string">''</span>)
                 <span class="hljs-comment">// set the message</span>
                <span class="hljs-keyword">return</span> setMessage(data.message)
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> setError(data.message)
            }


    } <span class="hljs-keyword">catch</span> (err) {
        console.error(<span class="hljs-string">'error happened here'</span>, err)
    }

}
    <span class="hljs-keyword">return</span> (
        <span class="hljs-operator">&lt;</span>div className<span class="hljs-operator">=</span><span class="hljs-string">"m-60 p-10 mt-20 px-70 border-1  bg-blue-200  flex flex-col shadow-2xl rounded-lg w-11/12 inset-5"</span><span class="hljs-operator">&gt;</span>



                     {<span class="hljs-function"><span class="hljs-keyword">error</span> ? &lt;<span class="hljs-title">ErrorAlert</span> <span class="hljs-title"><span class="hljs-keyword">error</span></span>=</span>{<span class="hljs-function"><span class="hljs-keyword">error</span>} /&gt; : <span class="hljs-title">null</span>}

                </span>{message ? <span class="hljs-operator">&lt;</span>SuccessAlert <span class="hljs-built_in">msg</span><span class="hljs-operator">=</span>{message}<span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>: null}

        <span class="hljs-operator">&lt;</span>strong className<span class="hljs-operator">=</span><span class="hljs-string">"underline "</span><span class="hljs-operator">&gt;</span>Imagination <span class="hljs-keyword">is</span> a powerful tool<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>strong<span class="hljs-operator">&gt;</span>


        <span class="hljs-operator">&lt;</span>form onSubmit<span class="hljs-operator">=</span>{postGoal} className<span class="hljs-operator">=</span><span class="hljs-string">"form my-2 flex flex-col"</span><span class="hljs-operator">&gt;</span>

        <span class="hljs-operator">&lt;</span>label className<span class="hljs-operator">=</span><span class="hljs-string">"p-2 decoration-solid    "</span><span class="hljs-operator">&gt;</span>Your Life<span class="hljs-operator">/</span>Current Goal<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>input className<span class="hljs-operator">=</span><span class="hljs-string">"form-input border border-gray-400 p-2 rounded-lg appearance-none focus:border-gray-500 focus:outline-none mb-2"</span> name<span class="hljs-operator">=</span><span class="hljs-string">"description"</span> value<span class="hljs-operator">=</span>{description} onChange<span class="hljs-operator">=</span>{(e)<span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>setDescription(e.target.<span class="hljs-built_in">value</span>)} <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text"</span> placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Your Goal"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>

                    <span class="hljs-operator">&lt;</span>label className<span class="hljs-operator">=</span><span class="hljs-string">"p-2 decoration-solid    "</span> <span class="hljs-operator">&gt;</span>Name<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
                    <span class="hljs-operator">&lt;</span>input className<span class="hljs-operator">=</span><span class="hljs-string">"form-input border border-gray-400 p-2  rounded-lg appearance-none focus:border-gray-500 mb-2 focus:outline-none"</span> name<span class="hljs-operator">=</span><span class="hljs-string">"name"</span> value<span class="hljs-operator">=</span>{name} onChange<span class="hljs-operator">=</span>{(e)<span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>setName(e.target.<span class="hljs-built_in">value</span>)}   <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"text"</span> placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Your name"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>         

                    <span class="hljs-operator">&lt;</span>label className<span class="hljs-operator">=</span><span class="hljs-string">"p-2 decoration-solid"</span><span class="hljs-operator">&gt;</span>Your Age <span class="hljs-operator">&lt;</span>i className<span class="hljs-operator">=</span><span class="hljs-string">"fa fa-twitter"</span> aria<span class="hljs-operator">-</span>hidden<span class="hljs-operator">=</span><span class="hljs-string">"true"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>i<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>label<span class="hljs-operator">&gt;</span>
                    <span class="hljs-operator">&lt;</span>input <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"number"</span> className<span class="hljs-operator">=</span><span class="hljs-string">"form-input border border-gray-400 p-2 mb-4 rounded-lg appearance-none mb-2 focus:border-gray-500 focus:outline-none"</span> name<span class="hljs-operator">=</span><span class="hljs-string">"age"</span> value<span class="hljs-operator">=</span>{age} onChange<span class="hljs-operator">=</span>{(e) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>setAge(e.target.<span class="hljs-built_in">value</span>)}  placeholder<span class="hljs-operator">=</span><span class="hljs-string">"Your Age (years old)"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>



            <span class="hljs-operator">&lt;</span>button <span class="hljs-keyword">type</span><span class="hljs-operator">=</span><span class="hljs-string">"submit"</span> className<span class="hljs-operator">=</span><span class="hljs-string">"rounded-full bg-blue-600  p-1 border border-gray-600"</span><span class="hljs-operator">&gt;</span>Submit<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>button<span class="hljs-operator">&gt;</span>

    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>form<span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
)   
}
</code></pre><h1 id="heading-alert-components">Alert Components</h1>
<p>The components used to display the status of API call are stored in directory `/Components/Alert/index.js</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">AlertStyle</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'./Alerts.module.css'</span>
<span class="hljs-title">export</span> <span class="hljs-title">const</span> <span class="hljs-title">SuccessAlert</span> <span class="hljs-operator">=</span> ({<span class="hljs-title"><span class="hljs-built_in">msg</span></span> }) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
{
    <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
        <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span>{<span class="hljs-title">AlertStyle</span>.<span class="hljs-title">successDiv</span>}<span class="hljs-operator">&gt;</span>
            ✅  {<span class="hljs-title"><span class="hljs-built_in">msg</span></span>}
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
    )
}
<span class="hljs-title">export</span> <span class="hljs-title">const</span> <span class="hljs-title">ErrorAlert</span> <span class="hljs-operator">=</span> ({<span class="hljs-title"><span class="hljs-keyword">error</span></span> }) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
{
    <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
        <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span>{<span class="hljs-title">AlertStyle</span>.<span class="hljs-title">errorDiv</span>}<span class="hljs-operator">&gt;</span>❗❗   {<span class="hljs-title"><span class="hljs-keyword">error</span></span>}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
    )
}
</code></pre><p>styling  for alertComponents is in Alerts.module.css</p>
<pre><code><span class="hljs-selector-class">.successDiv</span>{
<span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">21</span>, <span class="hljs-number">177</span>, <span class="hljs-number">21</span>);
<span class="hljs-attribute">color</span>:white;
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
<span class="hljs-attribute">padding</span>:<span class="hljs-number">10px</span>;
<span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
<span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">25rem</span>;
}
<span class="hljs-selector-class">.errorDiv</span>{
<span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">223</span>, <span class="hljs-number">65</span>, <span class="hljs-number">60</span>);
<span class="hljs-attribute">color</span>:white;
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
<span class="hljs-attribute">padding</span>:<span class="hljs-number">10px</span>;
<span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
<span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">25rem</span>;

}
</code></pre><h2 id="heading-little-cheating-with-mongodb">Little cheating with mongoDB</h2>
<p>To make this work, we are doing a brute force, hard document generation in the mongodb collection 'goals' using atlas cluster UI.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651147352876/Qj4ePdiA9.png" alt="explicit creation of goalsArray from Atlas cluster UI.png" /></p>
<h1 id="heading-pagesapigoals">🌐 /pages/api/goals</h1>
<p>This is the api endpoint, where we will handle all the requests made to db via certain events. The GET method is used in the <code>/goals</code> age to render all the goals, for which, UI code is down below.</p>
<pre><code>
<span class="hljs-keyword">import</span> <span class="hljs-title">clientPromise</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'../../../lib/mongodb'</span>


<span class="hljs-title">export</span> <span class="hljs-title">default</span> <span class="hljs-title">async</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">handler</span>(<span class="hljs-title">req</span>, <span class="hljs-title">res</span>){

    <span class="hljs-title">switch</span>(<span class="hljs-title">req</span>.<span class="hljs-title">method</span>){
        <span class="hljs-title">case</span> <span class="hljs-string">'POST'</span>:
            <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">addGoal</span>(<span class="hljs-title">req</span>, <span class="hljs-title">res</span>)
        <span class="hljs-title">case</span> <span class="hljs-string">'GET'</span> :
            <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">getGoals</span>(<span class="hljs-title">req</span>,<span class="hljs-title">res</span>)
    }
}


<span class="hljs-title">async</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">getGoals</span>(<span class="hljs-title">req</span>, <span class="hljs-title">res</span>){
    <span class="hljs-title"><span class="hljs-keyword">try</span></span> {
        <span class="hljs-comment">//connect to database</span>
        <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-string">'hitting api'</span>)
 <span class="hljs-title">const</span> <span class="hljs-title">client</span> <span class="hljs-operator">=</span> <span class="hljs-title">await</span> <span class="hljs-title">clientPromise</span>;
 const db <span class="hljs-operator">=</span> client.db()
 const goal<span class="hljs-operator">=</span> await db.collection(<span class="hljs-string">'goals'</span>).find()
 const response <span class="hljs-operator">=</span>await goal.next()
 const goalsArray <span class="hljs-operator">=</span> response.goalsArray
 console.log(`<span class="hljs-built_in">this</span> <span class="hljs-keyword">is</span> ${response}`)
console.log(response.goalsArray)
        <span class="hljs-keyword">return</span> res.json({goalsArray})
    } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
         <span class="hljs-comment">// return an error</span>
         <span class="hljs-keyword">return</span> res.json({
            message: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-function"><span class="hljs-keyword">error</span>).<span class="hljs-title">message</span>,
            <span class="hljs-title">success</span>: <span class="hljs-title"><span class="hljs-literal">false</span></span>,
        })
    }
}


<span class="hljs-title">async</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">addGoal</span> (<span class="hljs-params">req, res</span>)</span>{


    <span class="hljs-keyword">try</span> {
        let goal <span class="hljs-operator">=</span> JSON.parse(req.body);
       <span class="hljs-comment">// console.log(goal)</span>

        let{ name, age, description} <span class="hljs-operator">=</span>goal

        <span class="hljs-keyword">if</span>(<span class="hljs-operator">!</span>name <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-operator">!</span>age <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-operator">!</span>description){
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Invalid Request"</span>);
        }
        <span class="hljs-comment">//connect to database</span>
 const client <span class="hljs-operator">=</span> await clientPromise;
 const db <span class="hljs-operator">=</span> client.db()


<span class="hljs-comment">//POST request</span>
const response <span class="hljs-operator">=</span> await db.collection(<span class="hljs-string">'goals'</span>).updateOne({}, { $push: { <span class="hljs-string">"goalsArray"</span>: goal } })
 console.log(response)

<span class="hljs-comment">//return a message</span>
<span class="hljs-keyword">return</span> res.json({
    message: <span class="hljs-string">'Details updated successfully'</span>,
    success: response
})
    } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
        <span class="hljs-comment">// return an error</span>
        <span class="hljs-keyword">return</span> res.json({
            message: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-function"><span class="hljs-keyword">error</span>).<span class="hljs-title">message</span>,
            <span class="hljs-title">success</span>: <span class="hljs-title"><span class="hljs-literal">false</span></span>,
        })
    }
}</span>
</code></pre><h1 id="heading-ui-so-far">📈 📈UI so far</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651059070275/xOMM0FeHEB.png" alt="UI screen 1.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651059081327/eitlUJUhr.png" alt="UI screen 2.png" /></p>
<h1 id="heading-pagesgoals">/pages/goals 🔆🔆</h1>
<p>This page renders the list of goals. There are two components built to deliver the UI of this page.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">Head</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'next/head'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">GoalsList</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'../Components/Goals/GoalsList'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">Link</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'next/link'</span>
<span class="hljs-title">const</span> <span class="hljs-title">Goals</span><span class="hljs-operator">=</span>()<span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>{
    <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
    <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"container"</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-title">Head</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">title</span><span class="hljs-operator">&gt;</span><span class="hljs-title">All</span> <span class="hljs-title">Goals</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">title</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">link</span> <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"icon"</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"/favicon.ico"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">link</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"</span> <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>

   <span class="hljs-operator">&lt;</span><span class="hljs-title">link</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"</span> <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> <span class="hljs-title">integrity</span><span class="hljs-operator">=</span><span class="hljs-string">"sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We"</span> <span class="hljs-title">crossOrigin</span><span class="hljs-operator">=</span><span class="hljs-string">"anonymous"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">link</span><span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">Head</span><span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-title">main</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">' box-content  items-center px-10 py-4'</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">h1</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"title box-content pt-4 "</span><span class="hljs-operator">&gt;</span><span class="hljs-title">Goals</span> <span class="hljs-title">of</span> <span class="hljs-title">our</span> <span class="hljs-title">Generation</span> 👀👀<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">h1</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">strong</span> <span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-title">img</span> <span class="hljs-title">src</span><span class="hljs-operator">=</span><span class="hljs-string">"/pointer.png"</span> <span class="hljs-title">alt</span><span class="hljs-operator">=</span><span class="hljs-string">"pointer icon"</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"icon float-right"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-title">Link</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">'/goals'</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"subtitle pt-2 float-right"</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-title">You</span> <span class="hljs-title">can</span> <span class="hljs-title">add</span> <span class="hljs-title">your</span> <span class="hljs-title">goal</span> <span class="hljs-title">to</span> <span class="hljs-title"><span class="hljs-built_in">this</span></span> <span class="hljs-title">list</span>, <span class="hljs-title">here</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">Link</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">main</span><span class="hljs-operator">&gt;</span>
         <span class="hljs-operator">&lt;</span><span class="hljs-title">GoalsList</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
         <span class="hljs-operator">&lt;</span><span class="hljs-title">footer</span> <span class="hljs-operator">&gt;</span> 
        <span class="hljs-operator">&lt;</span><span class="hljs-title">a</span>
          <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://vercel.com?utm_source=create-next-app&amp;utm_medium=default-template&amp;utm_campaign=create-next-app"</span>
          <span class="hljs-title">target</span><span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span>
          <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"noopener noreferrer"</span>
        <span class="hljs-operator">&gt;</span>
          <span class="hljs-title">Powered</span> <span class="hljs-title">by</span> <span class="hljs-title">Vercel</span> 
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">a</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span> <span class="hljs-title">Made</span> <span class="hljs-title">with</span> ❣️<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">a</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://www.twitter.com/agrit_tiwari"</span><span class="hljs-operator">&gt;</span> @<span class="hljs-title">agrit_tiwari</span> <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">a</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">footer</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>)
}

<span class="hljs-title">export</span> <span class="hljs-title">default</span> <span class="hljs-title">Goals</span>
</code></pre><h1 id="heading-goalslist-component">GoalsList Component</h1>
<p>TO render the goals in such a fashion that latest added  goal is rendered at the top, we must blend custom css along with tailwind in example. Custom CSS also gives more freedom with developer tools as well.
The components directory is like this: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651255528353/y7SoCGrJk.png" alt="Component Directory.png" /></p>
<h3 id="heading-componentsgoalsgoalslistjsx">/Components/Goals/GoalsList.jsx</h3>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">React</span>, { <span class="hljs-title">useEffect</span>,<span class="hljs-title">useState</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'react'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">GoalCard</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'./GoalCard'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">styles</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'./Goals.module.css'</span>

<span class="hljs-title">const</span> <span class="hljs-title">GoalsList</span> <span class="hljs-operator">=</span> () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    <span class="hljs-title">const</span> [<span class="hljs-title">data</span>, <span class="hljs-title">setData</span>] <span class="hljs-operator">=</span> <span class="hljs-title">useState</span>([])
    <span class="hljs-title">const</span> [<span class="hljs-title">isLoading</span>, <span class="hljs-title">setLoading</span>] <span class="hljs-operator">=</span> <span class="hljs-title">useState</span>(<span class="hljs-title"><span class="hljs-literal">false</span></span>)

<span class="hljs-title">useEffect</span>(()<span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>{
    <span class="hljs-title">setLoading</span>(<span class="hljs-title"><span class="hljs-literal">true</span></span>)
    <span class="hljs-title">fetch</span>(<span class="hljs-string">'api/goals'</span>)
      .<span class="hljs-title">then</span>((<span class="hljs-title">res</span>) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-title">res</span>.<span class="hljs-title">json</span>())
      .<span class="hljs-title">then</span>((<span class="hljs-title">data</span>) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        <span class="hljs-title">setData</span>(<span class="hljs-title">data</span>.<span class="hljs-title">goalsArray</span>)
        <span class="hljs-title">setLoading</span>(<span class="hljs-title"><span class="hljs-literal">false</span></span>)
      })
},[])

<span class="hljs-title"><span class="hljs-keyword">if</span></span> (<span class="hljs-title">isLoading</span>) <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-operator">&lt;</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span><span class="hljs-title">Loading</span>...<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span>
  <span class="hljs-title"><span class="hljs-keyword">if</span></span> (<span class="hljs-operator">!</span><span class="hljs-title">data</span>) <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-operator">&lt;</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span><span class="hljs-title">No</span> <span class="hljs-title">profile</span> <span class="hljs-title">data</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span>
<span class="hljs-comment">//console.log(data)</span>
    <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
    <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span>{` <span class="hljs-title">$</span>{<span class="hljs-title">styles</span>.<span class="hljs-title">list</span>}`}<span class="hljs-operator">&gt;</span>
{<span class="hljs-title">data</span>.<span class="hljs-title">map</span>(( <span class="hljs-title">goal</span>,<span class="hljs-title">index</span>)<span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>(<span class="hljs-operator">&lt;</span><span class="hljs-title">GoalCard</span> <span class="hljs-title">key</span><span class="hljs-operator">=</span>{<span class="hljs-title">index</span>} <span class="hljs-title">goal</span><span class="hljs-operator">=</span>{<span class="hljs-title">goal</span>}<span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>))}    
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
  )
}

<span class="hljs-title">export</span> <span class="hljs-title">default</span> <span class="hljs-title">GoalsList</span>
</code></pre><h3 id="heading-componentsgoalsgoalcardjsx">/Components/Goals/GoalCard.jsx</h3>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">React</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'react'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">styles</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'./Goals.module.css'</span>
<span class="hljs-title">const</span> <span class="hljs-title">GoalCard</span> <span class="hljs-operator">=</span> ({<span class="hljs-title">goal</span>}) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
  <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
    <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span>{` <span class="hljs-title">$</span>{<span class="hljs-title">styles</span>.<span class="hljs-title">card</span>}`}<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span>{`<span class="hljs-title">$</span>{<span class="hljs-title">styles</span>.<span class="hljs-title">cardDiv1</span>}`}<span class="hljs-operator">&gt;</span>
        {<span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-title">goal</span>)}
        <span class="hljs-operator">&lt;</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span>👉 {<span class="hljs-title">goal</span>.<span class="hljs-title">description</span>}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">span</span><span class="hljs-operator">&gt;</span>{<span class="hljs-title">goal</span>.<span class="hljs-title">date</span>.<span class="hljs-title">slice</span>(4, 15)}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">span</span><span class="hljs-operator">&gt;</span>, <span class="hljs-operator">&lt;</span><span class="hljs-title">span</span><span class="hljs-operator">&gt;</span>{<span class="hljs-title">goal</span>.<span class="hljs-title">date</span>.<span class="hljs-title">slice</span>(16, 21)} <span class="hljs-title">IST</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">span</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span>{`<span class="hljs-title">$</span>{<span class="hljs-title">styles</span>.<span class="hljs-title">cardDiv2</span>}`}<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span>🗣️{<span class="hljs-title">goal</span>.<span class="hljs-title">name</span>}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span>{<span class="hljs-title">goal</span>.<span class="hljs-title">age</span>} <span class="hljs-title"><span class="hljs-literal">years</span></span> <span class="hljs-title">old</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">p</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
  )
}

<span class="hljs-title">export</span> <span class="hljs-title">default</span> <span class="hljs-title">GoalCard</span>
</code></pre><h3 id="heading-componentsgoalsgoalsmodulecss">/Components/Goals/Goals.module.css</h3>
<pre><code><span class="hljs-selector-class">.list</span>{

    <span class="hljs-attribute">width</span>:<span class="hljs-number">550px</span>;
    <span class="hljs-attribute">list-style-type</span>: none;
    <span class="hljs-attribute">display</span>: flex; 
    <span class="hljs-attribute">flex-direction</span>: column-reverse; 
    <span class="hljs-attribute">vertical-align</span>: top;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
<span class="hljs-attribute">background-color</span>: rgb(<span class="hljs-number">221</span>, <span class="hljs-number">148</span>, <span class="hljs-number">70</span>);


}

<span class="hljs-selector-class">.card</span>{
<span class="hljs-attribute">background-color</span>: rgb(<span class="hljs-number">172</span>, <span class="hljs-number">175</span>, <span class="hljs-number">177</span>);
<span class="hljs-attribute">border-radius</span>:<span class="hljs-number">20px</span>;
<span class="hljs-attribute">padding</span>:<span class="hljs-number">10px</span> <span class="hljs-number">4px</span> <span class="hljs-number">8px</span> <span class="hljs-number">4px</span>;

<span class="hljs-attribute">margin</span>: <span class="hljs-number">4px</span>;
}

<span class="hljs-selector-class">.cardDiv1</span>{
    <span class="hljs-attribute">margin</span>:<span class="hljs-number">5px</span>;;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">98%</span>;
    <span class="hljs-attribute">background-color</span>: rgb(<span class="hljs-number">209</span>, <span class="hljs-number">206</span>, <span class="hljs-number">208</span>);
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">6px</span>;

}
<span class="hljs-selector-class">.cardDiv1</span> &gt; <span class="hljs-selector-tag">p</span>{
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
   <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">0%</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10%</span>;
    <span class="hljs-comment">/* border: 1px solid rgb(46, 46, 46);  */</span>
    <span class="hljs-attribute">text-decoration-color</span>: rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.603</span>);
    <span class="hljs-attribute">text-decoration</span>: solid;
    <span class="hljs-attribute">text-shadow</span>: darkblue;
    <span class="hljs-attribute">text-align</span>: center;

}
<span class="hljs-selector-class">.cardDiv1</span> &gt; <span class="hljs-selector-tag">span</span>{
    <span class="hljs-attribute">text-align</span>: right;
}
<span class="hljs-selector-class">.timezone</span>{
    <span class="hljs-attribute">font-size</span>: smaller;
}
<span class="hljs-selector-class">.cardDiv2</span>{
   <span class="hljs-attribute">margin</span>: <span class="hljs-number">7px</span>;
   <span class="hljs-attribute">width</span>: <span class="hljs-number">98%</span>;
    <span class="hljs-attribute">background-color</span>: rgb(<span class="hljs-number">209</span>, <span class="hljs-number">206</span>, <span class="hljs-number">208</span>);
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2px</span>;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">6px</span>;
}

<span class="hljs-selector-class">.cardDiv2</span> &gt; <span class="hljs-selector-tag">p</span>{

    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
    <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
    <span class="hljs-attribute">text-align</span>: end;
    <span class="hljs-attribute">margin-right</span>:<span class="hljs-number">2px</span> ;
}
</code></pre><h1 id="heading-pagesindexjs">/pages/index.js</h1>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">Head</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'next/head'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> { <span class="hljs-title">GoalForm</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'../Components/Form'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">clientPromise</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'../lib/mongodb'</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">Link</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'next/link'</span>


<span class="hljs-title">export</span> <span class="hljs-title">default</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">Home</span>({ <span class="hljs-title">isConnected</span> }) {
  <span class="hljs-title"><span class="hljs-keyword">return</span></span> (
    <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"container "</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">Head</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">title</span><span class="hljs-operator">&gt;</span><span class="hljs-title">Write</span> <span class="hljs-title">your</span> <span class="hljs-title">Life</span> <span class="hljs-title">Goal</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">title</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">link</span> <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"icon"</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"/favicon.ico"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">link</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"</span> <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>

   <span class="hljs-operator">&lt;</span><span class="hljs-title">link</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"</span> <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"stylesheet"</span> <span class="hljs-title">integrity</span><span class="hljs-operator">=</span><span class="hljs-string">"sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We"</span> <span class="hljs-title">crossOrigin</span><span class="hljs-operator">=</span><span class="hljs-string">"anonymous"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">link</span><span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">Head</span><span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-title">main</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">'box-content  items-center px-10'</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">h1</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"title box-content  pt-4 "</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-title">Write</span> <span class="hljs-title">about</span> <span class="hljs-title">your</span> <span class="hljs-title">life</span> <span class="hljs-title">Goal</span> 🥇💭
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">h1</span><span class="hljs-operator">&gt;</span>

        {<span class="hljs-title">isConnected</span> ? (<span class="hljs-operator">&lt;</span><span class="hljs-title">div</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"flow-root"</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-title">strong</span> <span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-title">img</span> <span class="hljs-title">src</span><span class="hljs-operator">=</span><span class="hljs-string">"/pointer.png"</span> <span class="hljs-title">alt</span><span class="hljs-operator">=</span><span class="hljs-string">"pointer icon"</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"icon float-right"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-title">Link</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">'/goals'</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"subtitle pt-2 float-right"</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-title">See</span> <span class="hljs-title">the</span> <span class="hljs-title">List</span> <span class="hljs-title">of</span> <span class="hljs-title">all</span> <span class="hljs-title">wonderful</span> <span class="hljs-title">Goals</span> <span class="hljs-title">people</span> <span class="hljs-title">are</span> <span class="hljs-title">working</span> <span class="hljs-title">on</span> <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">Link</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>

        ) : (
          <span class="hljs-operator">&lt;</span><span class="hljs-title">h2</span> <span class="hljs-title">className</span><span class="hljs-operator">=</span><span class="hljs-string">"subtitle box-content  "</span><span class="hljs-operator">&gt;</span>
          <span class="hljs-title">There</span> <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">no</span> <span class="hljs-title">access</span> <span class="hljs-title">to</span> <span class="hljs-title">Dreamland</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">h2</span><span class="hljs-operator">&gt;</span>
        )}
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">main</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">GoalForm</span><span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-title">footer</span> <span class="hljs-operator">&gt;</span> 
        <span class="hljs-operator">&lt;</span><span class="hljs-title">a</span>
          <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://vercel.com?utm_source=create-next-app&amp;utm_medium=default-template&amp;utm_campaign=create-next-app"</span>
          <span class="hljs-title">target</span><span class="hljs-operator">=</span><span class="hljs-string">"_blank"</span>
          <span class="hljs-title">rel</span><span class="hljs-operator">=</span><span class="hljs-string">"noopener noreferrer"</span>
        <span class="hljs-operator">&gt;</span>
          <span class="hljs-title">Powered</span> <span class="hljs-title">by</span> <span class="hljs-title">Vercel</span> 
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">a</span><span class="hljs-operator">&gt;</span>
<span class="hljs-operator">&lt;</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span> <span class="hljs-title">Made</span> <span class="hljs-title">with</span> ❣️<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">strong</span><span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-title">a</span> <span class="hljs-title">href</span><span class="hljs-operator">=</span><span class="hljs-string">"https://www.twitter.com/agrit_tiwari"</span><span class="hljs-operator">&gt;</span> @<span class="hljs-title">agrit_tiwari</span> <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">a</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">footer</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-title">div</span><span class="hljs-operator">&gt;</span>
  )
}

<span class="hljs-title">export</span> <span class="hljs-title">async</span> <span class="hljs-title"><span class="hljs-keyword">function</span></span> <span class="hljs-title">getServerSideProps</span>(<span class="hljs-title">context</span>) {
  <span class="hljs-title"><span class="hljs-keyword">try</span></span> {
    <span class="hljs-title">await</span> <span class="hljs-title">clientPromise</span>
    <span class="hljs-comment">// `await clientPromise` will use the default database passed in the MONGODB_URI</span>
    <span class="hljs-comment">// However you can use another database (e.g. myDatabase) by replacing the `await clientPromise` with the folloing code:</span>
    <span class="hljs-comment">//</span>
    <span class="hljs-comment">// `const client = await clientPromise`</span>
    <span class="hljs-comment">// `const db = client.db("myDatabase")`</span>
    <span class="hljs-comment">//</span>
    <span class="hljs-comment">// Then you can execute queries against your database like so:</span>
    <span class="hljs-comment">// db.find({}) or any of the MongoDB Node Driver commands</span>

    <span class="hljs-title"><span class="hljs-keyword">return</span></span> {
      <span class="hljs-title">props</span>: { <span class="hljs-title">isConnected</span>: <span class="hljs-title"><span class="hljs-literal">true</span></span> },
    }
  } <span class="hljs-title"><span class="hljs-keyword">catch</span></span> (<span class="hljs-title">e</span>) {
    <span class="hljs-title">console</span>.<span class="hljs-title"><span class="hljs-keyword">error</span></span>(<span class="hljs-title">e</span>)
    <span class="hljs-title"><span class="hljs-keyword">return</span></span> {
      <span class="hljs-title">props</span>: { <span class="hljs-title">isConnected</span>: <span class="hljs-title"><span class="hljs-literal">false</span></span> },
    }
  }
}
</code></pre><h1 id="heading-ui-pagesgoalsjs">UI 🎴🎴/pages/goals.js</h1>
<p>The UI of the following code is like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651255905200/FbcUr_OyH.png" alt="goals page.png" /></p>
<h1 id="heading-deployed-on-vercelhttpswwwvercelcom">Deployed on <a target="_blank" href="https://www.vercel.com">Vercel</a>🌐</h1>
<p>This is the link for version-1 towards building full fledged app on nextJS + mongodb.</p>
<p><a target="_blank" href="nextjs-mongodb-v1.vercel.app">nextjs-mongodb-v1.vercel.app</a> or  <a target="_blank" href="https://goals-of-our-generation.vercel.app/">https://goals-of-our-generation.vercel.app/</a></p>
<h2 id="heading-thanks-for-following-along">🌼🌼Thanks for following along.</h2>
<p>Thanks <a target="_blank" href="https://twitter.com/JCSmiley4">JC Smile</a> for reviewing.</p>
]]></content:encoded></item><item><title><![CDATA[Explaining Web Rendering with NextJS]]></title><description><![CDATA[As developers, you are faced with decision to choose stack which will affect the entire architecture of the web application. It depends on the usecase of the application and so it does define where to implement logic and rendering in their applicatio...]]></description><link>https://tech-blog.agrittiwari.com/web-rendering</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/web-rendering</guid><category><![CDATA[Next.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[web performance]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Wed, 02 Feb 2022 15:09:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643814510156/rSjSn7eKe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As developers, you are faced with decision to choose stack which will affect the entire architecture of the web application. It depends on the usecase of the application and so it does define where to implement logic and rendering in their application.</p>
<p>This blog is written to demonstrate various approaches of rendering on web and discussing the pros and cons of each way. The differences between these approaches help illustrate the trade-offs of rendering on the web through the lens of performance.</p>
<p>Web performance is itself a large field, but with the advent of <a target="_blank" href="https://nextjs.org/">NextJS</a>. It becomes easy to demonstrate the effect of different rendering approaches under its umbrella. </p>
<h2 id="heading-follow-this-projecthttpsdevkode-novembertalks-nextjsvercelapp">👉 <a target="_blank" href="https://devkode-novembertalks-nextjs.vercel.app/">Follow this project</a></h2>
<p>Do open <code>network tab</code> in chrome devtools .</p>
<ul>
<li>Client SIde Rendering</li>
<li>Server Side Rendering</li>
<li>Static Side Generation</li>
</ul>
<h1 id="heading-client-side-rendering">Client Side Rendering</h1>
<p>Client-side rendering (CSR) means rendering pages directly in the browser using JavaScript. All logic, data fetching, templating and routing are handled on the client rather than the server.</p>
<blockquote>
<ul>
<li>Server renders the page without any dynamic data</li>
<li>Client Immediately shows the page (without any dynamic data) </li>
<li>Page displays a loading state (for missing dynamic data) </li>
<li>NextJS makes all of the API calls (to fetch dynamic data) </li>
<li>NextJS renders the missing dynamic data on the client side</li>
</ul>
</blockquote>
<p>👉 Check that there is no data like neighbouring countries in the source code of the /csr  route of the <a target="_blank" href="https://devkode-novembertalks-nextjs.vercel.app/">project</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643800127279/IvGsXUddg.png" alt="client-rendering-tti.png" />
This diagram can be verified in the network tab of chrome dev tools. In this <a target="_blank" href="https://devkode-novembertalks-nextjs.vercel.app/">project</a>, take note of TTFB (Time to First Byte) and compare.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><em>Pros of CSR</em></td></tr>
</thead>
<tbody>
<tr>
<td>1. Fast Server Side Rendering</td></tr>
<tr>
<td>2.Page gets displayed immediately</td></tr>
<tr>
<td>3. Build Single Page Application</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><em>Cons of CSR</em></td></tr>
</thead>
<tbody>
<tr>
<td>1. No initial render of dynamic data</td></tr>
<tr>
<td>2. Bad for SEO</td></tr>
</tbody>
</table>
</div><h1 id="heading-server-side-rendering">Server Side Rendering</h1>
<p>Server-side Rendering or SSR  generates the full HTML for a page on the server in response to navigation. This avoids additional round-trips for data fetching and templating on the client, since it’s handled before the browser gets a response.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643809149242/KLa0MluTp.png" alt="server-rendering-tti.png" />
This diagram can be verified in the network tab of chrome dev tools. In this <a target="_blank" href="https://devkode-novembertalks-nextjs.vercel.app/">project</a>, take note of TTFB (Time to First Byte) and compare.</p>
<p>👉 <a target="_blank" href="https://devkode-novembertalks-nextjs.vercel.app/">In this project</a> as well, you can see there is no loading state as it were in the csr route. The content is prerendered on the server and sent to client. It does increase the TTFB.</p>
<p>👉What NextJS does fantastically well is it provides <code>&lt;Link/&gt;</code> tag that supports prefetch of the content and NextJS sents an API reques to the server  and server runs the <code>getserversideprops</code>,
server returns json as a response NextJS uses the JSON to render the page and provides wonderful experience for the heavy server side rendered pages so that first interaction gets quicker on client side page request.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><em>Pros of SSR</em></td></tr>
</thead>
<tbody>
<tr>
<td>1. Dynamic content is readily available</td></tr>
<tr>
<td>2. Good for SEO</td></tr>
<tr>
<td>3. Page has no blank loading state, since its pre rendered.</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><em>Cons of SSR</em></td></tr>
</thead>
<tbody>
<tr>
<td>1. Slowest TTFB (due to pre-rendering)</td></tr>
<tr>
<td>2. Results cannot be cached by CDN without extra configuration</td></tr>
<tr>
<td>3. Results cannot be cached by a CDN without extra CDN.</td></tr>
</tbody>
</table>
</div><h1 id="heading-static-rendering-or-static-site-generation">Static Rendering or Static Site Generation</h1>
<p>Static Rendering happens at build time, the pages are pregenerated with static content and markup and has very low client side javascript. Static renders can be deployed to multiple CDNs to take advantage of edge-caching. This gives the ability to load the static content in a fastest manner, the only time it takes is during bundling and build of the code. Each page is part of the build and thus there is increased bundle size, but it is fair with the usecase.</p>
<p>👉<a target="_blank" href="https://devkode-novembertalks-nextjs.vercel.app/">In this project</a>, you can experience the loading speed of statically generated page on <code>/ssg</code> route. You can also checkout my portfolio at <a target="_blank" href="www.agrittiwari.com">www.agrittiwari.com</a> which has articles section as demonstration of SSG.</p>
<p>👉Do check the source code of <code>/ssg</code> page as it will have all of the content in it which was absent in the <code>/csr</code>.</p>
<p>👉 You can read about <code>Incremental Static Regeneration here</code> which is a wonderful add-on on Static Site Generation <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration">here</a>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643811191126/Br268RDL7.png" alt="static-rendering-tti.png" /></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><em>Pros of SSG</em></td></tr>
</thead>
<tbody>
<tr>
<td>1. Incredibly fast.</td></tr>
<tr>
<td>2. Built once and pages get cached by CDN for a long time.</td></tr>
<tr>
<td>3. Great for SEO.</td></tr>
<tr>
<td>4. Build offline progressive web apps.</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><em>Cons of SSG</em></td></tr>
</thead>
<tbody>
<tr>
<td>1. Slow Server Side site builds.</td></tr>
<tr>
<td>2. Build time gets more as the static pages increase in the bundle.</td></tr>
<tr>
<td>3. Not good for frequently changing content portions.</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion 🧐</h2>
<p>So, the web rendering is subjected to the use case and business requirement as it has been classified and developed based on its merits and demerits. I hope you learnt something from the article and you can refer to the <a target="_blank" href="https://github.com/agrittiwari/devkode-novembertalks-nextjs">repository of this project</a> I built for a talk in a community (devKode).</p>
<blockquote>
<p>Feel free to star ⭐️ the project if you found useful - github.com/agrittiwari/devkode-novembertalks-nextjs</p>
<p><a target="_blank" href="https://www.buymeacoffee.com/agrittiwari">Buy me a book 📚</a></p>
</blockquote>
<h2 id="heading-thank-you">Thank you 😇👋</h2>
]]></content:encoded></item><item><title><![CDATA[Errors you encounter in javascript language]]></title><description><![CDATA[The major hurdle of a language always seems to be the errors we are stuck at. Some errors could hold us for days, if not a week. But the errors are the best teacher of a programming language. An error is the display of your mistake, who else these da...]]></description><link>https://tech-blog.agrittiwari.com/errors-you-encounter-in-javascript-language</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/errors-you-encounter-in-javascript-language</guid><category><![CDATA[error handling]]></category><category><![CDATA[error]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Fri, 28 Jan 2022 06:50:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643352522422/23gTWuJ4V.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The major hurdle of a language always seems to be the errors we are stuck at. Some errors could hold us for days, if not a week. But the errors are the best teacher of a programming language. An error is the display of your mistake, who else these days tell you your mistake with a direction to resolve it. The errors you face in any programming language are the steps that you must face to establish a fundamental level understanding of the language. There are concepts and functioning that you seem to grasp quickly, but errors made the quirks of a language very clear to you. And we are talking about javascript, which is a very quirky language. You must know the errors you face to build a solution oriented nature whenever you see an error on your screen.</p>
<h1 id="heading-errors">Errors</h1>
<h2 id="heading-1-syntax-error">1. Syntax Error</h2>
<p>This is the most common Error and it happens when you use wrong syntax in comparison to predefined syntax. 
For example -</p>
<pre><code>let <span class="hljs-type">name</span> = <span class="hljs-string">'agrittiwari'</span>:
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643350345732/Dw057M_au.png" alt="syntax error.png" /></p>
<h2 id="heading-2-reference-error">2. Reference Error</h2>
<p>Reference Error is thrown when we want to refer a variable that does not exist, it means the variable is not declared.
For example -</p>
<pre><code>let name <span class="hljs-operator">=</span> <span class="hljs-string">'agrittiwari'</span>;
console.log(age);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643350636685/oJ4rgJogk.png" alt="reference error.png" /></p>
<h2 id="heading-3range-error">3.Range Error</h2>
<p>RangeError is thrown to indicate that a passed function argument does not fall within the valid set or range of acceptable values.
For example -</p>
<pre><code><span class="hljs-keyword">let</span> arr = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(<span class="hljs-number">50000000000</span>);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643350977918/SCPXQXWzs.png" alt="range error.png" />
The maximum number of elements that you can set for an array is ( 2^32 -1 )</p>
<h2 id="heading-4type-error">4.Type Error</h2>
<p>The TypeError object represents an error when an operation could not be performed, typically (but not exclusively) when a value is not of the expected type.</p>
<p>A TypeError may be thrown when:</p>
<p>an operand or argument passed to a function is incompatible with the type expected by that operator or function; or
when attempting to modify a value that cannot be changed; or
when attempting to use a value in an inappropriate way</p>
<p>For example - </p>
<pre><code><span class="hljs-keyword">let</span> <span class="hljs-built_in">number</span> = <span class="hljs-number">5</span>;
<span class="hljs-built_in">number</span>.split(<span class="hljs-string">""</span>);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643351399352/KgCbPAAs_.png" alt="Type error.png" /></p>
<h2 id="heading-5-uri-error">5. URI Error</h2>
<p>URI - Uniform Resource Identifier
URI in javascript has the functions such as decodeURI(), decodeURIComponent(), Etc., ANd the URIError is thrown whenever a wrong character(s) is used in URI function. For example -</p>
<pre><code><span class="hljs-selector-tag">decodeURIComponent</span>(<span class="hljs-string">"%"</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643351766117/b5FW02rsE.png" alt="URI error.png" /></p>
<h2 id="heading-6-eval-error">6. Eval Error</h2>
<p>The Eval Error just simply indicates an error regarding the global <code>eval()</code> method.</p>
<blockquote>
<p>This is no longer thrown by the current javascript engine or EcmaScript Specification. However, it still exists for backward compatibility.</p>
</blockquote>
<h2 id="heading-7-internal-error">7. Internal Error</h2>
<p>This error occurs internally in the JS engine, especially when it has too much data to handle and the stack grows way over its critical limit.</p>
<p>This also occurs when the JS engine is overwhelmed by too many recursions, Switch cases, etc.</p>
<p>Debugging errors is the skill of a pro programmer and it can only be sharpen by resolving as much errors as you can from your codebase. It is a great way to strengthen your core concepts about the language.</p>
<p>Thank you for reading!!</p>
]]></content:encoded></item><item><title><![CDATA[How to use GitHub effectively as a Contributor?]]></title><description><![CDATA[Whenever you get the opportunity to work on a project as a Contributor, meaning you have access rights to do almost anything with the repository. You must follow certain practices and etiquettes to make meaningful contribution without screwing the so...]]></description><link>https://tech-blog.agrittiwari.com/how-to-use-github-effectively-as-a-contributor</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/how-to-use-github-effectively-as-a-contributor</guid><category><![CDATA[Continuous Integration]]></category><category><![CDATA[continuous deployment]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Thu, 05 Aug 2021 08:15:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1628149933681/FkZmIxzkZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whenever you get the opportunity to work on a project as a Contributor, meaning you have access rights to do almost anything with the repository. You must follow certain practices and etiquettes to make meaningful contribution without screwing the software development Life cycle and workflow and  to reflect your professionalism by elegantly managing your role as a Contributor.</p>
<h2 id="starting-as-a-github-contributor">Starting as a GitHub Contributor</h2>
<p>Just get started with your project by setting up the project locally cloning the main repo, using HTTPS method <code>git clone &lt;repo_url&gt;.git</code> or Github CLI.</p>
<p>In case you are restarting your work as Contributor on a project, make a pull request to the main branch to make your local version up-to date with remote main.</p>
<p><code>git pull main</code></p>
<h2 id="before-you-start-working">Before you start working</h2>
<p>Before you start working on your local machine, it is better to checkout to a new branch to change you current branch so as to have a local main to go back in case of endless loop or unorganisable state of code and prevent any unwanted future push.</p>
<p><code>git checkout -b &lt;new_branchname&gt;</code></p>
<p>You can switch back to main or any other branch you created locally by simply
 <code>git switch &lt;branchname&gt;</code></p>
<h2 id="when-its-time-to-commit-your-contributions">When its time to commit your contributions</h2>
<p>When you've added changes and made your contributions to the new branch you created, you want to give meaning to that contribution by pushing it to remote main. But, never ever directly push to main branch, it is best to follow this flow to commit your changes,</p>
<pre><code>git <span class="hljs-keyword">add</span> .
git <span class="hljs-keyword">commit</span> -m  "&lt;meaningful comment about changes you made or features you added&gt;"
</code></pre><p>then you need to push these change to your remote branch that you created locally, It gives a certain confidence and a good second eye  check on your code before actually pushing it to main.</p>
<p><em>Very Important</em> <code>git push origin &lt;branchname&gt;</code></p>
<p>Your commits will reflect on the remote repository on your branch and an option to create a pull request. While creating a pull request, take a look at changes and provide a little explanation about the feature or changes you added with respect to main branch in the comment section.</p>
<h2 id="dont-use-your-ability-to-merge-all-the-time">Don't use your ability to merge all the time</h2>
<p>As a contributor, you got access to merge any pull request to the main, but do not excessively merge the requests to main. It may breakdown the workflow for other and then they need to update their local version more randomly. Alert rest of the contributors about the pending merges and announce about it before/after merge, so they don't have to work on the out-of date version of the product. This boosts your credibility and trust. <a target="_blank" href="https://tech-blog.agrittiwari.com/how-to-collaborate-on-a-project-working-remotely">Read more here</a></p>
<h2 id="keep-your-local-setup-up-to-date">Keep your local setup up-to-date</h2>
<p>Its clear to you about the changes you made, but to be  reassured about the version you are currently working is up-to-date. Make sure to fetch the latest version of  remote main and merge it with your local setup and reiterate the steps form step 2.</p>
<pre><code>git fetch origin
git <span class="hljs-keyword">merge</span> origin/<span class="hljs-keyword">main</span>
</code></pre><p>This basic flow of doing contributions may prove to be helpful to boost your effectiveness as a Github Contributor. Till then, keep coding and keep contributing. You can read more <a target="_blank" href="https://project-display-and-stack-notes.vercel.app/posts/basic-github-setup">here</a></p>
<p>#contribution #github #community</p>
]]></content:encoded></item><item><title><![CDATA[How to collaborate on a project working remotely?]]></title><description><![CDATA[There will opportunities come before you to collaborate on a project, sometimes the collaboration is on a local level with a possible mutual understanding and backgrounds, where there is no awkardness to began induldging into project development dire...]]></description><link>https://tech-blog.agrittiwari.com/how-to-collaborate-on-a-project-working-remotely</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/how-to-collaborate-on-a-project-working-remotely</guid><category><![CDATA[Collaboration]]></category><category><![CDATA[remote]]></category><category><![CDATA[projects]]></category><category><![CDATA[Experience ]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Wed, 04 Aug 2021 06:29:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1628055235601/wL18is-y-.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There will opportunities come before you to collaborate on a project, sometimes the collaboration is on a local level with a possible mutual understanding and backgrounds, where there is no awkardness to began induldging into project development directly. And sometimes the atmosphere and team for the project to collaborate is of different backgrounds, where there is discomfort to start the conversation and difficulty to begun with collaboration on project development. For that, I am writing the key points that helped me and given a refreshing experience while collaborating on a project working remotely.</p>
<h2 id="focus-on-your-tech-stack-strengths">Focus on your Tech stack strengths</h2>
<p>Do not forget that this collaboration is initiated for the building of a project. Put focus on your tech stack strengths and take responsibilities to build certain parts and functionalities of the project. Do not wait for someone to direct you in some direction and follow along the development journey of the project. If your stack strengths are already taken by someone else, do not hesitate to learn a new stack either. And continuously give your feedback and contributions that you wanted to take responsibility of.</p>
<h2 id="live-coding-and-debugging">Live coding and debugging</h2>
<p>Connect on a zoom call and live share your code, do talk about what you are coding or debugging in that call. It maintains flow of information fluent. Do not engage in other task while you are live sharing session is still on, it reflects your busyness. Ask them to schedule sessions in your free time. Dedicated multiple coders in meeting counts to numerous eyes and as they say, "second eye is always a good debugger" . So it will boost productivty and boost your project development.</p>
<h2 id="ask-questions">Ask Questions</h2>
<p>Do ask away any question that bugs your understanding of the code. It is the reason to collaborate with high skilled teammates, that you learn to ask good questions and grow your skills. Honing your skills comes from great question and great question arises from in-depth code-reviewing. Do read other player's code as it will help you to understand the overall flow of your project from scratch. And knowing the actual reason of something that happens in code is the real learning you should seek in a collaboration.</p>
<h2 id="learn-how-to-use-github-effectively-as-a-contributor">Learn how to use github effectively as a Contributor!</h2>
<p>Learning how to use github for collaboration on a project while working remotely is very crucial because it is the platform that provides you the traction from the friction of localhood. Learning how to contribute on github repo without disturbing the main branch of project is an important skill to learn. And only way to learn is by doing. Do as much as possible of github contribution to inculcate the habit of creating pull request for contribution to main branch.</p>
<h2 id="communication-is-the-key">Communication is the key</h2>
<p>Interact clearly as much as possible with your teammates. Declare your intentions and ideas openly without any hesitation. Do not preconceive any judgement or comment from your respective teammates. Talk to them with respect and apologise on events when communication is flawed or intent is misinterpreted or your actions caused some error in the Software/Application development life cycle. It will all happen, but you neeed to learn to explain your intent and apologise for the mistake and learn from it.</p>
<p>#collaboration #communication #mintbean #remote #remotework</p>
]]></content:encoded></item><item><title><![CDATA[Accessibility and the React Ecosystem]]></title><description><![CDATA[Definitiion of Accessibility
 " Web accessibility is the design and creation of websites that can be used by everyone. Accessibility support is necessary to allow assistive technology to interpret web pages "
Its about making or solving for everyone
...]]></description><link>https://tech-blog.agrittiwari.com/accessibility-and-the-react-ecosystem</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/accessibility-and-the-react-ecosystem</guid><category><![CDATA[Web Accessibility]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[React]]></category><category><![CDATA[React Native]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Mon, 02 Aug 2021 13:27:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627910641667/EF_ieiC4Z.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="definitiion-of-accessibility">Definitiion of Accessibility</h2>
<p> " Web accessibility is the design and creation of websites that can be used by everyone. Accessibility support is necessary to allow assistive technology to interpret web pages "</p>
<p>Its about making or solving for everyone
Making your website responsive</p>
<h2 id="what-is-officially-accessibilty">What is officially Accessibilty?</h2>
<p>-&gt; Access the web in better ability, enabling keyboard navigation, voice-to-text feature, enabling mouse scroll events; overall better User Experience</p>
<h2 id="how-to-make-accessibility-rich-web-apps">How to make accessibility rich web-apps?</h2>
<p>-&gt; With web, generally we follow Web Content Accessibility Guideine (WCGA)</p>
<ul>
<li><p>Perceivable part :
adding attributes to semantic HTML, 
alt tag to <img /> element, 
making form accessible through keyboard,
enabling navigation through keyboard, 
adding lang attribute in HTML, etc.</p>
</li>
<li><p>Robust:
use standardised semantic  element like <code>&lt;article/&gt;</code> because it helps screen reader users to navigate,
key board first approach for operable part </p>
</li>
</ul>
<h3 id="different-level-of-accessibilty">Different level of Accessibilty</h3>
<ul>
<li>Level A -&gt; <a target="_blank" href="Accessible Rich Internet Applications">Aria level</a></li>
<li>Level AA -&gt; allows yout to hear captions</li>
<li>Level AAA -&gt; sign language implementation (extreme level)</li>
</ul>
<blockquote>
<p>AI and machine learning algorithms are leading way to increase power of browser.</p>
</blockquote>
<ul>
<li>In web, tab order, tab index</li>
</ul>
<h3 id="native-mobile-accessibilty">Native mobile Accessibilty</h3>
<p>Android and iOS have  different specification for WCGA</p>
<ul>
<li><p>Android has <em>talk-back</em> and iOS has <em>voice-Over</em> , these are screen readers to provide focus on some  elements. Read more on this <a target="_blank" href="https://usability.yale.edu/web-accessibility/articles/focus-keyboard-operability">here</a>.</p>
</li>
<li><p><strong>There are different defaults, no possible one-to-one mapping  when we consider android and iOS separately</strong></p>
</li>
</ul>
<h2 id="how-we-can-enable-accessibility-in-react">How we can enable accessibility in React?</h2>
<ul>
<li>Use component from multiple libraries like Modals to avoid edge cases; Libraries like <a target="_blank" href="https://material-ui.com/">material-ui</a> and <a target="_blank" href="https://npm.io/package/@material-ui/unstyled">unstyle</a>  are good options as mostly they cover accessibiility roles well, like focus trapping, tab-index; Just go with which comes with less styling baggage.</li>
</ul>
<h3 id="react-aria-and-react-spectrumhttpsreact-spectrumadobecomreact-ariagetting-startedhtml"><a target="_blank" href="https://react-spectrum.adobe.com/react-aria/getting-started.html">React aria and React Spectrum</a></h3>
<ul>
<li>The way Adobe team decoupled accessibility via hooks into JSX is supercool. Keyboard, mouse and tab accessible.</li>
</ul>
<p>-Another library <a target="_blank" href="https://github.com/downshift-js/downshift">downshift</a></p>
<h2 id="reactnative-ariahttpsreact-native-ariageekyantscom">(Reactnative aria](https://react-native-aria.geekyants.com/)</h2>
<ul>
<li>Platform agnostic  (agnostic means  something that is generalized so that it is interoperable among various systems)
-Accessibility labels, content-description attributes; which abstracts via hooks into JSX.
-Like for pressible elements to make a checkbox in RN, you need to pass correct accessible label and state which returns react-native api which passed back into props.
-Like to split/abstract out the behavior via hooks to improve accessibility. This library help us to build component with high accessibility.</li>
</ul>
<h3 id="write-once-for-everywhere-is-the-future">Write once for everywhere is the future</h3>
<ul>
<li>Reactnative provide <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles"><code>WAI-ARIA roles</code></a>. <strong>How it can be mapped back to web via reactnative-web</strong></li>
<li>In RN web, there is much missing, but  highe chances to boost accessibility on the web.</li>
<li>RN web has alternative ways to provide web semantic via APIs like  and do DOM things better</li>
<li>Reactnative web is better approach to take react everywhere.</li>
<li>React has done agreat job. Universal/monorepo is the way to go.</li>
<li>The trend these days is app should look same on every platform; UI is more likely to go universal.</li>
</ul>
<h3 id="work-in-this-direction">Work in this direction</h3>
<ul>
<li>GAAD (Global Accessibility Awareness Day) its a pledge to make products accessible.</li>
<li>NextJS and Typescript is pushing towards building more accessible apps.</li>
<li>Have easy and right defaults.</li>
</ul>
<h3 id="tools-to-check-accessibility-level">Tools to check accessibility level</h3>
<ul>
<li><a target="_blank" href="https://developers.google.com/web/tools/lighthouse">Lighthouse</a></li>
<li><em>Manual testing is irreplacable</em></li>
<li><a target="_blank" href="https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor&amp;hl=en_IN&amp;gl=US">Accessibility scanner app</a></li>
</ul>
<h2 id="future-of-accessibility">Future of Accessibility</h2>
<ul>
<li>*Don't read it as feature,take it as ego.</li>
<li>Industry is showing inclination towards it.</li>
<li>Universal is the way to go, we need universal debuggers, like <a target="_blank" href="https://github.com/facebook/flipper">Flipper</a> by Facebook </li>
<li>We need devtools focused on Accessibility.</li>
</ul>
<p>Follow me on <a target="_blank" href="https://www.twitter.com/agrit_tiwari">twitter</a> to know more about technology and development. A bit of philosophy too. </p>
<p>inspired from a Twitter space hosted by <a target="_blank" href="https://twitter.com/geekyants">@GeekyAnts</a></p>
]]></content:encoded></item><item><title><![CDATA[How to deploy a MERN stack application on Heroku]]></title><description><![CDATA[A full-fledged application is the calming tune of every developer. As the functionality of the application and feature grow, the application demands a database and a backend to interact with it too.
A newbie learning to develop applications suffers t...]]></description><link>https://tech-blog.agrittiwari.com/how-to-deploy-a-mern-stack-application-on-heroku</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/how-to-deploy-a-mern-stack-application-on-heroku</guid><category><![CDATA[deployment]]></category><category><![CDATA[Heroku]]></category><category><![CDATA[mern-stack]]></category><category><![CDATA[MERN Stack]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Tue, 25 May 2021 07:23:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621927221508/LrUOIPWIs.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A full-fledged application is the calming tune of every developer. As the functionality of the application and feature grow, the application demands a database and a backend to interact with it too.
A newbie learning to develop applications suffers the over-diverse pool of syntax, one for the frontend, one for the backend, and another level of understanding to establish a concurrent run of both frontend and backend. But if you are a javascript enthusiast, that's not the case for you.</p>
<p>You can learn to code and develop a full-fledged application within the realm of your javascript syntax. The solution is the MERN stack which comprises <a target="_blank" href="https://university.mongodb.com/">MongoDB</a> ( a NoSQL database), <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction#introducing_express">Express</a> (a backend server framework), <a target="_blank" href="https://reactjs.org/docs/getting-started.html">React</a> (a frontend javascript framework), and <a target="_blank" href="https://nodejs.org/en/docs/">Node</a> ( a javascript runtime environment out of browser).</p>
<p><a target="_blank" href="https://cloud.mongodb.com/"><em>We are using MongoDB atlas -a cloud database</em></a></p>
<p>After building your MERN stack application, seeing it running locally on your machine at localhost://3000 certainly good, but to make it employer-ready, you should host it. I will show you how to deploy it on <a target="_blank" href="https://signup.heroku.com/">Heroku</a> (container-based cloud Platform as a Service (PaaS) used to deploy, manage, and scale modern apps). Make your account.</p>
<ul>
<li>Folder Structure
You should follow the same folder structure to run scripts effectively.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621923165886/NNTN8ybTP.png" alt="Folder structure for MERN stack.png" /></li>
</ul>
<p>Your backend files and modules should be in the root folder directory (:/project_folder/) and your frontend in a folder in your root folder (:/project_folder/client_folder) Client folder is react frontend folder in the above image.</p>
<ul>
<li>Scripts for starting, building, and deploying your project<pre><code> "scripts": {
      "start": "node server.js",
      "server": "nodemon server.js",
      "client": "cd client &amp;&amp; npm start ",
      "dev": "concurrently -n 'server,client' -c 'red,green' \"npm run <span class="hljs-keyword">server</span>\" \"npm run client\"",
      "heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client &amp;&amp; npm run build --prefix client"
  }
</code></pre></li>
<li><p>Edit the server.js  to deploy only in production environment mode</p>
<pre><code><span class="hljs-selector-tag">if</span>(process.env.NODE_ENV === <span class="hljs-string">'production'</span>){
<span class="hljs-comment">//set static folder</span>
<span class="hljs-selector-tag">app</span><span class="hljs-selector-class">.use</span>(express.static(<span class="hljs-string">'client/build'</span>));
<span class="hljs-selector-tag">app</span><span class="hljs-selector-class">.get</span>(<span class="hljs-string">'*'</span>,(req,res) =&gt; res.sendFile(path.resolve(__dirname, <span class="hljs-string">'client'</span>, <span class="hljs-string">'build'</span>, <span class="hljs-string">'index.html'</span>)));
}
</code></pre><ul>
<li>Install the <a target="_blank" href="https://devcenter.heroku.com/articles/heroku-cli#download-and-install">Heroku CLI</a>
Check installation success with <code>heroku -v</code> in the command line. It will show you the version.</li>
</ul>
</li>
<li>Go to your project directory and <code>heroku login</code>. This will invoke login in your browser.</li>
<li>Run <code>heroku create</code>. It will create a domain name for your project to get hosted. </li>
<li><p>Git repository
You should make a local git repository for your project initialized in the root folder. Learn <a target="_blank" href="https://vickyikechukwu.hashnode.dev/introduction-to-git-in-16-minutes">git</a> here.
Your changes should be up to date with the repository. To make sure,</p>
<pre><code>git init
git <span class="hljs-keyword">add</span> .
git <span class="hljs-keyword">commit</span> -m "Preparing to Deploy
</code></pre></li>
<li><p>Now you need to add Heroku as a remote repository. Go to your <a target="_blank" href="https://dashboard.heroku.com/apps">Heroku dashboard</a> and open your project with the same domain name. Go to the deploy section and you will see a command like</p>
<pre><code>heroku git remote -a  {heroku-project-<span class="hljs-type">name</span>}
</code></pre></li>
<li>After adding Heroku as remote repository, you can push your project to Heroku by <pre><code>git <span class="hljs-keyword">push</span> heroku master
</code></pre>It will run that post-build script that's going to build our react static assets and create the build folder
and our backend will load that index.html file and our application will deploy. You can see your deployed application by <code>heroku open</code>.
To deploy the updated features, you must follow the same.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Component LifeCycle methods]]></title><description><![CDATA[In react, every component goes through a process called component lifecycle. This component lifecycle explains the interactivity of data to UI on the page.

So, first, a Component will mount and the constructor() where the class instance gets created...]]></description><link>https://tech-blog.agrittiwari.com/component-lifecycle-methods</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/component-lifecycle-methods</guid><category><![CDATA[React]]></category><category><![CDATA[components]]></category><category><![CDATA[class]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Sun, 16 May 2021 11:05:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621163010557/uA_XWlC4d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In react, every component goes through a process called component lifecycle. This component lifecycle explains the interactivity of data to UI on the page.</p>
<ul>
<li>So, first, a Component will mount and the constructor() where the class instance gets created and the state gets instantiated. And it renders, basically put UI to the page.</li>
<li>And whenever setState() gets called or new props are received, it needs to re-render, it will update UI. This part of the lifecycle updates and re-renders with some lifecycle methods. </li>
<li>And when there comes time for a component to disappear or when you need to clear something that you created in the mount stage, it is removed in Unmount stage.</li>
</ul>
<p>You can follow this diagram to visualize the lifecycle of a component.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620656633363/Ppjj1Thf8.png" alt="1_uEiKgYmcmVfbDNywvGBbVQ.png" /></p>
<h3 id="lets-see-what-it-means-in-practice">Let's see what it means in Practice</h3>
<h2 id="mount">Mount</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="
&lt;iframe src=">" data-card-controls="0" data-card-theme="light"&gt;
<iframe src="https://codesandbox.io/embed/recursing-montalcini-kejut?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe></a></div>
<blockquote>
<p>Use Slider to see the code</p>
</blockquote>
<ul>
<li>Constructor(props)<ul>
<li>initialize state or other class properties (e.g , bound methods)</li>
</ul>
</li>
<li>render()<ul>
<li>the meat of a component</li>
<li>return a node</li>
</ul>
</li>
<li>componentDidMount()<ul>
<li>Do anything that isn't needed for UI (async actions, timers, etc.)</li>
<li>setting state here will cause a re-render before updating the UI</li>
</ul>
</li>
</ul>
<h2 id="update">Update</h2>
<p>Just like in the Mounting cycle, a bunch of lifecycle hooks are called in the update cycle, every single time we want to re-render.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="&lt;iframe src=">" data-card-controls="0" data-card-theme="light"&gt;<iframe src="https://codesandbox.io/embed/update-stage-in-react-lifecycle-toyd1?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe></a></div>
<ul>
<li>componentWillReceiveProps(nextProps)<ul>
<li>update any state fields that rely on props.
-shouldComponentUpdate(nextProps, nextState)</li>
<li>compare changed values,before rendering. return true id the component should re-render</li>
<li>if returned false, update cycle will terminate.</li>
<li>Almost always a premature condition.</li>
</ul>
</li>
<li>render()</li>
<li>componentDidUpdate(prevProps, prevState)<ul>
<li>Do anything  that isn't needed for UI (network requests, api call etc). </li>
</ul>
</li>
</ul>
<p>In update cycle, firstly shouldComponentUpdate() is invoked, then render() and only then componentDidUpdate().</p>
<h2 id="unmount">Unmount</h2>
<p>This is an important stage of the component lifecycle. It is where cleanup is performed after the component is unmounted. The reason to clean up after unmounting any timers,  background calls is to optimize the application for the user's intended experience. An application must compute the result with full memory usage designated to the task at hand, not lag due to past actions. Pending requests must get eliminated as soon as the interaction with the specific component is over.</p>
<p>If we do not unmount the component, background calls, functioning will keep on running and stacking up the memory. See thi example. Check the console and press the toggle button.
%[<iframe src="https://codesandbox.io/embed/unmount-stage-problem-tnjye?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>]</p>
<p> To solve the problem we must register an unmount stage after the use of the component is done. As it will clear the space and will optimize the whole application</p>
<ul>
<li>ComponentWillUnmount()<ul>
<li>clean up
~ Remove event Listeners
~ Invalidate Network Requests
~ Clear timeouts/intervals</li>
</ul>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="&lt;iframe src=">" data-card-controls="0" data-card-theme="light"&gt;<iframe src="https://codesandbox.io/embed/need-of-unmounting-the-react-component-ddoby?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe></a></div>
<p>Error Handling: <a target="_blank" href="https://reactjs.org/docs/react-component.html#error-handling">Here</a> 
You can continue learning about <a target="_blank" href="............">lifecycle hooks for functional Component</a></p>
]]></content:encoded></item><item><title><![CDATA[Components in React]]></title><description><![CDATA[Components are reusable and independent building blocks of a react app. They are the same as a javascript function but return a node (something that can be rendered). They represent a discrete piece of UI. Component-based architecture in React is the...]]></description><link>https://tech-blog.agrittiwari.com/components-in-react</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/components-in-react</guid><category><![CDATA[React]]></category><category><![CDATA[components]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Mon, 10 May 2021 07:35:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620632605512/1M_5oGPLJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Components are reusable and independent building blocks of a react app. They are the same as a javascript function but return a node (something that can be rendered). They represent a discrete piece of UI. Component-based architecture in React is the reason for independent code structure and resolved complexity of interactivity.</p>
<p>You can visualize components by following this diagram.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620574230113/9nkx14ljLX.png" alt="1_r9d_WyshaCfZSfqzubR1Yg.png" /></p>
<ul>
<li><p>All React components must act like pure functions with respect to their <a target="_blank" href="https://reactjs.org/docs/components-and-props.html">props</a></p>
</li>
<li><p>Two types:
1.Class-based Component
2.Functional Component</p>
</li>
</ul>
<h2 id="class-based-component">Class-based Component</h2>
<p>(We also call it React.Component)  Just like in Javascript, there is a class that has only one method render() which simply returns the react element (JSX).</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyName</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span></span>{
render(){
<span class="hljs-keyword">return</span>(
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, My name is Agrit Tiwari<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
)
}}
</code></pre><p>In this above example, We can also pass data from outside the component. It will remove the barrier of hard code. We now know props come from above. You can read more about props <a target="_blank" href="https://github.com/uberVU/react-guide/blob/master/props-vs-state.md">here</a></p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyName</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span></span>{
render(){
<span class="hljs-keyword">return</span>(
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, My name is {this.props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
)}}

<span class="hljs-keyword">const</span> knowMe = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyName</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Agrit Tiwari"</span> /&gt;</span></span>
</code></pre><ul>
<li><p>An abstract class that can be extended to behave however you want.
-These have additional features that SFC don't have:</p>
</li>
<li><p>Have instances
*Maintain their own state</p>
</li>
<li>Have lifeCycle methods( similar to hooks and event listeners) that are automatically invoked.</li>
<li>Rendering is a function of props and class properties</li>
</ul>
<p>In class Components,  we update the UI by updating the state within the component by using Lifecycle methods. <a target="_blank" href="https://tech-blog.agrittiwari.com/component-lifecycle-methods">Learn about Lifecycle methods</a></p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskToDo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span></span>{
<span class="hljs-keyword">constructor</span>(props){
<span class="hljs-built_in">super</span>(props)
<span class="hljs-built_in">this</span>.state ={
numOfTasks = <span class="hljs-number">0</span>
}
}
incTasks(){
<span class="hljs-built_in">this</span>.setstate({ <span class="hljs-attr">numoFTasks</span> :<span class="hljs-built_in">this</span>.state.numOfTasks +<span class="hljs-number">1</span>})
}
decTasks(){
<span class="hljs-built_in">this</span>.setstate({<span class="hljs-attr">numOFTasks</span>: <span class="hljs-built_in">this</span>.state.numOfTasks <span class="hljs-number">-1</span>})
}
render(){
<span class="hljs-keyword">return</span>(
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Tasks to do<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Tasks : {this.state.numOfTasks}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">(()</span> =&gt;</span> this.incTasks())&gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">(()</span> =&gt;</span> this.decTasks())&gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

)}
}
</code></pre><p>-this.state() is a class property on the component instance.
-setState calls are batched and run asynchronously.
-Changes in the state also cause re-renders.</p>
<h2 id="functional-component">Functional Component</h2>
<p>Functional Component in React also returns a node for the discrete piece of UI. They are classified into types based on their work and usage.
1.Stateless Functional Component:
The simplest component, we use them when we don't need a state in our application. This simply takes a prop and returns a node. Any change in props will cause the function to re-render. The function should be pure(It should not have any side effects like setting values, updating arrays, etc)</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">const</span> Emplyoee = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
<span class="hljs-keyword">return</span>(
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, My name is {props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>I work at {props.company}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)
}
</code></pre><p>This will only return the props attribute which is passed from another component.</p>
<p>2.Stateful Functional Component:
A stateful component can contain the state object and event handling function, user actions as well. This is the advancement of stateless components in order to do the manipulation of the data that needs to re-render. Stateful components make the UI interactive and made possible updation of state by virtue of React hooks. <a target="_blank" href="...........................">Learn about hooks here</a> </p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> Item = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> {
<span class="hljs-keyword">const</span> [worth, setworth ] =useState(<span class="hljs-number">0</span>)

<span class="hljs-keyword">return</span>(
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, My name is {details.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>I work at {details.company}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">(()</span>=&gt;</span> setWorth(worth + props.profit ) &gt;Set your Profit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)
}

<span class="hljs-keyword">const</span> ItemDetails = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Item</span> <span class="hljs-attr">details</span> = <span class="hljs-string">{item}</span> <span class="hljs-attr">profit</span>/&gt;</span></span>
<span class="hljs-keyword">const</span> item ={
<span class="hljs-attr">name</span>: <span class="hljs-string">"Bicycle"</span>,
<span class="hljs-attr">company</span>: <span class="hljs-string">"Atlas Cycles Ltd."</span>,
<span class="hljs-attr">Location</span>: <span class="hljs-string">"India"</span>
}
</code></pre><p>I hope this gives a clear understanding of the difference between the Class component and the Functional Component.</p>
]]></content:encoded></item><item><title><![CDATA[Getting Started with React Native]]></title><description><![CDATA[A little disclosure to the widely popular question i.e., Why build mobile apps with react native?

React Native is a cross-platform, single codebase stack for both native iOS and Android apps.
Uses React Javascript.
100% access to native APIs via Jav...]]></description><link>https://tech-blog.agrittiwari.com/getting-started-with-react-native</link><guid isPermaLink="true">https://tech-blog.agrittiwari.com/getting-started-with-react-native</guid><category><![CDATA[guide]]></category><category><![CDATA[React Native]]></category><category><![CDATA[Expo]]></category><dc:creator><![CDATA[Agrit Tiwari]]></dc:creator><pubDate>Mon, 12 Apr 2021 12:28:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618230432138/SmGooF3yd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A little disclosure to the widely popular question i.e., Why build mobile apps with react native?</p>
<ol>
<li>React Native is a cross-platform, single codebase stack for both native iOS and Android apps.</li>
<li>Uses React Javascript.</li>
<li>100% access to native APIs via Javascript and reuse of packages from NPM.</li>
<li>Backed by Facebook.
isn't it enough? </li>
</ol>
<p>Hey, It's most easy to set up and start development quickly.  I'll be providing 3 major ways in which you can complete your setup and begin your development journey in react native.</p>
<h1 id="snack">Snack</h1>
<p> If you'd like to try out React Native directly in your web browser before installing any tools, you can try out <a target="_blank" href="https://snack.expo.io">Snack</a>. It's the easiest way to work on react native with low system configurations and requirements. This platform is highly beneficial for learning and teaching purposes as well. 
And another advantage that you can build and host small react native projects on the  <a target="_blank" href="https://snack.expo.io">Snack</a>. It is much easier to share your project and get quick feedback from mentors. 
It's like Codepen for React Native.</p>
<h1 id="expo-cli">Expo Cli</h1>
<p>As you are getting started with React native, it is the most friendly choice, easy to begin with, and above all, supports live rendering of your code on your physical device. Seeing your code working on your physical device is quite a feeling of achievement. As I started development, I followed a lot of tutorials that were deprecated till that time, so I had to struggle a lot. And expo CLI has helped me set up my learning journey of react-native.
To begin with, Assuming that you have <a target="_blank" href="https://nodejs.org/en/download">NODE</a> installed, use your command line to install expo CLI</p>
<pre><code><span class="hljs-built_in">npm</span> install -g expo-cli
</code></pre><p> Then create a new React Native project using   </p>
<pre><code>expo init &lt;Project <span class="hljs-type">Name</span>&gt;
cd &lt;Project <span class="hljs-type">Name</span>&gt; 
expo <span class="hljs-keyword">start</span>
</code></pre><p>This will start a development server for you. And it will show a QR code that can be scanned by 
<a target="_blank" href="https://expo.io/client">Expo Go Client</a>. Expo app can be downloaded from your native app store on physical devices. This is a marvel to debug your app with live rendering and zero delay reloads.</p>
<h1 id="react-native-cli">React Native CLI</h1>
<p>React Native CLI is a little bit complex set up to begin the react-native developer journey and most appropriate for high complexity apps. The amount of work required in the setup is quite a lot and demands high-performance machine specification as it will require you to install an Android or an iOS simulator for live rendering on your screen. 
 I'll be rolling out tutorials on react native CLI as I prosper.</p>
<p>I highly suggest following the documentation for  <a target="_blank" href="https://reactnative.dev/docs/environment-setup">React Native</a> along with whatever course, tutorial, or Bootcamp. As I have been myself a victim of learning deprecated stuff, and I do not wish the same upon you. </p>
]]></content:encoded></item></channel></rss>