<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ React Native - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ React Native - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:30:26 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/react-native/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Create Fluid Animations with React Native Reanimated v4 ]]>
                </title>
                <description>
                    <![CDATA[ Reanimated 4 brings Cascading Style Sheets (CSS) animations to React Native while keeping full backward compatibility with its worklet-based API. You can now build 60+ frames-per-second (FPS) animations using familiar web syntax, or drop down to work... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-fluid-animations-with-react-native-reanimated-v4/</link>
                <guid isPermaLink="false">691b3eab5aa173ac953652e2</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react native reanimated ]]>
                    </category>
                
                    <category>
                        <![CDATA[ animation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Balogun Wahab ]]>
                </dc:creator>
                <pubDate>Mon, 17 Nov 2025 15:26:35 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763052228638/4416e81d-b76e-4c40-987e-0aff1d82ff7b.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Reanimated 4 brings Cascading Style Sheets (CSS) animations to React Native while keeping full backward compatibility with its worklet-based API. You can now build 60+ frames-per-second (FPS) animations using familiar web syntax, or drop down to worklets for gesture-driven interactions.</p>
<p>The library requires React Native's New Architecture (Fabric), so you'll need version 0.76 or newer.</p>
<p>In this tutorial, you'll learn:</p>
<ul>
<li><p>How to use CSS transitions for state-driven animations</p>
</li>
<li><p>When to use worklets for gesture and scroll interactions</p>
</li>
<li><p>How to migrate from Reanimated 3 to 4</p>
</li>
<li><p>Practical patterns for collapsing headers, bottom sheets, and carousels</p>
</li>
<li><p>Performance optimization techniques</p>
</li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>You should have:</p>
<ul>
<li><p>React Native 0.76+ with New Architecture enabled</p>
</li>
<li><p>Basic React hooks knowledge (useState, useEffect)</p>
</li>
<li><p>Node.js and npm or yarn are installed</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-installation-and-setup">Installation and Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-two-approaches">Understanding the Two Approaches (CSS Animations and Worklets)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-migrate-from-reanimated-version-3-to-version-4">How to Migrate from Reanimated Version 3 to Version 4</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-css-animations-tutorial">CSS Animations Tutorial</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-worklets-tutorial">Worklets Tutorial</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-patterns">Real-World Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-performance-optimizations">Performance Optimizations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-debugging-tips">Debugging Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-installation-and-setup">Installation and Setup</h2>
<p>To get started, you'll need to install the required packages:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># For Expo</span>
npx expo install react-native-reanimated react-native-worklets

<span class="hljs-comment"># For React Native CLI  </span>
npm install react-native-reanimated react-native-worklets
<span class="hljs-built_in">cd</span> ios &amp;&amp; pod install &amp;&amp; <span class="hljs-built_in">cd</span> ..
</code></pre>
<p>Update <code>babel.config.js</code> (the plugin must be last):</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">presets</span>: [<span class="hljs-string">'module:metro-react-native-babel-preset'</span>],
  <span class="hljs-attr">plugins</span>: [
    <span class="hljs-string">'react-native-worklets/plugin'</span>, <span class="hljs-comment">// Must be last</span>
  ],
};
</code></pre>
<p>Then clear the cache and rebuild:</p>
<pre><code class="lang-bash">npm start -- --reset-cache
npx react-native run-ios
</code></pre>
<h2 id="heading-understanding-the-two-approaches">Understanding the Two Approaches</h2>
<p>React Native Reanimated is an animation library that runs animations on the native thread instead of the JavaScript thread. This means your animations stay smooth even when your JavaScript code is busy processing data or handling user interactions.</p>
<p>Unlike React Native's built-in Animated API, Reanimated executes animation logic directly on the UI thread. This eliminates the performance bottleneck caused by communication between JavaScript and native code, which enables Reanimated to maintain 60 FPS even during complex operations.</p>
<p>Reanimated 4 offers two animation systems, each designed for different use cases.</p>
<h3 id="heading-css-animations">CSS Animations</h3>
<p>CSS animations work declaratively, meaning you describe what you want to happen rather than how to make it happen. You define which properties should animate (like width, color, or opacity), specify the timing and easing, then simply change the values through React state updates. Reanimated automatically handles the animation between the old and new values.</p>
<p>This approach excels at predictable, state-driven animations where you know both the starting and ending states. It's ideal for:</p>
<ul>
<li><p>Showing and hiding UI elements (modals, tooltips, notifications)</p>
</li>
<li><p>Expanding and collapsing content (accordions, dropdown menus)</p>
</li>
<li><p>Visual feedback for state changes (button hover effects, selection highlights)</p>
</li>
<li><p>Loading indicators and progress animations</p>
</li>
<li><p>Color and opacity transitions</p>
</li>
</ul>
<h3 id="heading-worklets">Worklets</h3>
<p>Worklets take a different approach by giving you imperative, frame-by-frame control over animations. They run on the UI thread and use "shared values" – special variables that can be accessed and modified from both JavaScript and native code without any communication overhead.</p>
<p>Worklets are essential for interactive animations that need to respond in real-time to user input or continuous data streams. They're best for:</p>
<ul>
<li><p>Gesture-driven interactions (drag-and-drop, swipe-to-dismiss, pinch-to-zoom)</p>
</li>
<li><p>Scroll-linked effects (parallax images, collapsing headers, sticky elements)</p>
</li>
<li><p>Physics-based animations (spring effects, momentum scrolling)</p>
</li>
<li><p>Sensor-based animations (responding to device orientation)</p>
</li>
<li><p>Any animation requiring dynamic, real-time control</p>
</li>
</ul>
<p>Now that you understand the two approaches Reanimated offers, let's look at how to migrate from version 3 if you're already using the library.</p>
<h2 id="heading-how-to-migrate-from-reanimated-version-3-to-version-4">How to Migrate from Reanimated Version 3 to Version 4</h2>
<p>If you're currently using Reanimated 3, you'll be happy to know that version 4 maintains backward compatibility. Your existing animations using worklets, shared values, and <code>useAnimatedStyle</code> will continue to work without modification.</p>
<p>But version 4 introduces some architectural changes and removes deprecated APIs, so you'll need to make a few updates to your project configuration and code. Let's walk through the migration process step by step.</p>
<h3 id="heading-what-changed-in-version-4">What Changed in Version 4</h3>
<p>The most significant change is that worklets have been extracted into a separate package called <code>react-native-worklets-core</code>. This modular approach allows other libraries beyond Reanimated to leverage worklet functionality.</p>
<p>Because of this separation, you'll need to update your Babel configuration. Change the plugin from <code>react-native-reanimated/plugin</code> to <code>react-native-worklets/plugin</code>.</p>
<p>Version 4 also exclusively supports React Native's New Architecture (Fabric). The old Paper renderer is no longer compatible. If your project hasn't migrated to the New Architecture yet, you'll need to either upgrade to React Native 0.76+ (which has New Architecture enabled by default) or stay on Reanimated 3.x until you're ready to make that transition.</p>
<h3 id="heading-removed-apis">Removed APIs</h3>
<p>Several APIs that were deprecated in version 3 have been removed in version 4. Here's what you need to replace:</p>
<ul>
<li><p><code>useAnimatedGestureHandler</code> → Use the <code>Gesture</code> API from react-native-gesture-handler 2.x instead</p>
</li>
<li><p><code>useWorkletCallback</code> → Use <code>useCallback</code> with the <code>'worklet'</code> directive</p>
</li>
<li><p><code>combineTransition</code> → Use <code>EntryExitTransition.entering().exiting()</code></p>
</li>
</ul>
<p>The <code>useScrollViewOffset</code> hook has been renamed to <code>useScrollOffset</code>. The old name still works but is deprecated, so update your code to use the new name.</p>
<h3 id="heading-spring-configuration-change">Spring Configuration Change</h3>
<p>The spring animation configuration has changed to feel more natural. The <code>duration</code> parameter now represents "perceptual duration" rather than exact milliseconds. The actual animation runs approximately 1.5 times longer than the specified duration, creating springs that feel more organic and less mechanical.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Version 3</span>
withSpring(<span class="hljs-number">100</span>, { <span class="hljs-attr">duration</span>: <span class="hljs-number">300</span> }) <span class="hljs-comment">// Runs for exactly 300ms</span>

<span class="hljs-comment">// Version 4  </span>
withSpring(<span class="hljs-number">100</span>, { <span class="hljs-attr">duration</span>: <span class="hljs-number">200</span> }) <span class="hljs-comment">// Runs for approximately 300ms</span>
</code></pre>
<p>If you need to maintain the exact timing from version 3, divide your duration values by 1.5.</p>
<h3 id="heading-step-by-step-migration-process">Step-by-Step Migration Process</h3>
<p>Here's how to migrate your project from Reanimated 3 to version 4:</p>
<p><strong>Step 1:</strong> Verify your project is using React Native 0.76 or newer with New Architecture enabled. Check your iOS Podfile for <code>ENV['RCT_NEW_ARCH_ENABLED'] = '1'</code> and your Android gradle.properties for <code>newArchEnabled=true</code>.</p>
<p><strong>Step 2:</strong> Install the new versions of Reanimated and the worklets package:</p>
<pre><code class="lang-bash">npm install react-native-reanimated@^4.1.0 react-native-worklets@^0.5.0
</code></pre>
<p><strong>Step 3:</strong> Update your <code>babel.config.js</code> to use the new worklets plugin:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">plugins</span>: [
    <span class="hljs-string">'react-native-worklets/plugin'</span>, <span class="hljs-comment">// Changed from react-native-reanimated/plugin</span>
  ],
};
</code></pre>
<p><strong>Step 4:</strong> Search your codebase for the removed APIs and replace them:</p>
<ul>
<li><p>Replace <code>useAnimatedGestureHandler</code> with the <code>Gesture</code> API</p>
</li>
<li><p>Replace <code>useWorkletCallback</code> with <code>useCallback</code> and add <code>'worklet'</code> directive</p>
</li>
<li><p>Replace <code>combineTransition</code> with <code>EntryExitTransition.entering().exiting()</code></p>
</li>
<li><p>Rename <code>useScrollViewOffset</code> to <code>useScrollOffset</code></p>
</li>
</ul>
<p><strong>Step 5:</strong> Rebuild your native apps:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ios &amp;&amp; pod install &amp;&amp; <span class="hljs-built_in">cd</span> ..
npx react-native run-ios
<span class="hljs-comment"># or for Android</span>
npx react-native run-android
</code></pre>
<p>After completing these steps, your app should be running on Reanimated 4 with all your existing animations working as before. You're now ready to start using the new CSS animation features alongside your existing worklet-based animations. In the next section, you'll learn how to build animations using the CSS syntax.</p>
<h2 id="heading-css-animations-tutorial">CSS Animations Tutorial</h2>
<p>CSS animations provide a clean, declarative way to handle transitions that are triggered by state changes. Instead of manually managing animation values, you simply declare which properties should animate and how, then update your component state – Reanimated handles the rest.</p>
<p>This approach is particularly powerful for animations where you know the start and end states ahead of time. It's perfect for UI elements that toggle between different visual states, like modals appearing and disappearing, buttons providing feedback on press, or content expanding and collapsing.</p>
<h3 id="heading-basic-transitions">Basic Transitions</h3>
<p>A transition animates the change between two property values. When you specify a property that should transition, Reanimated automatically interpolates between the old and new values over the specified duration.</p>
<p>Let's look at an expandable card that grows when tapped:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Pressable, Text } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> Animated <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-reanimated'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ExpandableCard</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [expanded, setExpanded] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Pressable</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> setExpanded(!expanded)}&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">width:</span> <span class="hljs-attr">expanded</span> ? <span class="hljs-attr">300</span> <span class="hljs-attr">:</span> <span class="hljs-attr">200</span>,
        <span class="hljs-attr">height:</span> <span class="hljs-attr">expanded</span> ? <span class="hljs-attr">200</span> <span class="hljs-attr">:</span> <span class="hljs-attr">100</span>,
        <span class="hljs-attr">backgroundColor:</span> <span class="hljs-attr">expanded</span> ? '#<span class="hljs-attr">4ade80</span>' <span class="hljs-attr">:</span> '#<span class="hljs-attr">86efac</span>',
        <span class="hljs-attr">transitionProperty:</span> ['<span class="hljs-attr">width</span>', '<span class="hljs-attr">height</span>', '<span class="hljs-attr">backgroundColor</span>'],
        <span class="hljs-attr">transitionDuration:</span> <span class="hljs-attr">300</span>,
        <span class="hljs-attr">transitionTimingFunction:</span> '<span class="hljs-attr">ease-in-out</span>',
      }}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Tap to toggle<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Pressable</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here's what's happening: The card's width, height, and background color are controlled by the <code>expanded</code> state. The <code>transitionProperty</code> array tells Reanimated which properties to animate. When <code>expanded</code> changes, Reanimated smoothly animates from the current values to the new values over 300 milliseconds, using an ease-in-out timing function that starts slow, speeds up, then slows down again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762274975831/7e25aa04-24b8-43eb-9db0-a3c088c44132.gif" alt="7e25aa04-24b8-43eb-9db0-a3c088c44132" class="image--center mx-auto" width="295" height="640" loading="lazy"></p>
<h3 id="heading-keyframe-animations">Keyframe Animations</h3>
<p>While transitions handle changes between two states, keyframe animations let you define multi-step sequences with precise control over each stage. You create an object where each key represents a percentage of the animation timeline, and the value defines what properties should look like at that point.</p>
<p>Here's a pulsing badge that scales up and fades slightly, then returns to normal:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> pulseAnimation = {
  <span class="hljs-string">'0%'</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span> },
  <span class="hljs-string">'50%'</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">1.05</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">0.8</span> },
  <span class="hljs-string">'100%'</span>: { <span class="hljs-attr">scale</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span> },
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PulsingBadge</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
      <span class="hljs-attr">width:</span> <span class="hljs-attr">50</span>,
      <span class="hljs-attr">height:</span> <span class="hljs-attr">50</span>,
      <span class="hljs-attr">borderRadius:</span> <span class="hljs-attr">25</span>,
      <span class="hljs-attr">backgroundColor:</span> '#<span class="hljs-attr">ef4444</span>',
      <span class="hljs-attr">animationName:</span> <span class="hljs-attr">pulseAnimation</span>,
      <span class="hljs-attr">animationDuration:</span> <span class="hljs-attr">2000</span>,
      <span class="hljs-attr">animationIterationCount:</span> '<span class="hljs-attr">infinite</span>',
    }} /&gt;</span></span>
  );
}
</code></pre>
<p>The animation starts at 0% (normal size and opacity), grows and fades at the 50% mark, then returns to the original state at 100%. By setting <code>animationIterationCount</code> to 'infinite', the animation loops continuously. This creates the pulsing effect you often see on notification badges or live indicators.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762274903470/d10d856f-03b8-4d6c-b616-22cbea3434c2.gif" alt="d10d856f-03b8-4d6c-b616-22cbea3434c2" class="image--center mx-auto" width="295" height="640" loading="lazy"></p>
<h3 id="heading-built-in-animations">Built-in Animations</h3>
<p>Reanimated includes a collection of pre-built animations for common entrance and exit effects. These save you from writing animation configurations for standard patterns like fading, sliding, and zooming.</p>
<p>Here's a modal that fades in when shown and fades out when hidden:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { FadeIn, FadeOut } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-reanimated'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Modal</span>(<span class="hljs-params">{ visible, children }</span>) </span>{
  <span class="hljs-keyword">if</span> (!visible) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> 
      <span class="hljs-attr">entering</span>=<span class="hljs-string">{FadeIn.duration(300)}</span>
      <span class="hljs-attr">exiting</span>=<span class="hljs-string">{FadeOut.duration(200)}</span>
    &gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span></span>
  );
}
</code></pre>
<p>The <code>entering</code> prop automatically applies the fade-in animation when the component mounts, and <code>exiting</code> applies the fade-out before unmounting. Other commonly used built-in animations include <code>SlideInRight</code>, <code>SlideOutLeft</code> (for drawer-style entrances), and <code>ZoomIn</code>, <code>ZoomOut</code> (for attention-grabbing pop-ins).</p>
<p>Now that you understand CSS animations for state-driven transitions, let's explore worklets for creating interactive animations that respond to user input in real-time.</p>
<h2 id="heading-worklets-tutorial">Worklets Tutorial</h2>
<p>While CSS animations excel at predefined state transitions, many animations need to respond dynamically to user input. This is where worklets come in. Worklets give you frame-by-frame control over animations, allowing them to follow gestures, scroll position, or any other real-time input source.</p>
<p>Interactive animations differ from CSS animations in that they don't have predefined start and end states. Instead, they continuously update based on user input. For example, a draggable element needs to follow your finger precisely as you move it – there's no way to know ahead of time where you'll drag it. This requires imperative control, where you directly manipulate animation values in response to events.</p>
<h3 id="heading-basic-worklet-animation">Basic Worklet Animation</h3>
<p>Shared values are the foundation of worklet-based animations. They're special variables that exist simultaneously in both the JavaScript and UI threads, allowing you to update them from JavaScript while the UI thread reads them to update the display – all without any communication overhead.</p>
<p>Here's a button that scales down when pressed and bounces back when released:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Animated, { 
  useSharedValue, 
  useAnimatedStyle, 
  withSpring 
} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-reanimated'</span>;
<span class="hljs-keyword">import</span> { Pressable } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BouncyButton</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> scale = useSharedValue(<span class="hljs-number">1</span>);

  <span class="hljs-keyword">const</span> animatedStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">transform</span>: [{ <span class="hljs-attr">scale</span>: scale.value }],
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Pressable</span>
      <span class="hljs-attr">onPressIn</span>=<span class="hljs-string">{()</span> =&gt;</span> { scale.value = withSpring(0.9); }}
      onPressOut={() =&gt; { scale.value = withSpring(1); }}
    &gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{[styles.button,</span> <span class="hljs-attr">animatedStyle</span>]}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Press Me<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Pressable</span>&gt;</span></span>
  );
}
</code></pre>
<p>The <code>useSharedValue(1)</code> creates a shared value initialized to 1 (normal scale). The <code>useAnimatedStyle</code> hook creates a style object that depends on this shared value and runs on the UI thread. When you press the button, <code>scale.value = withSpring(0.9)</code> updates the shared value, and <code>withSpring</code> creates a spring animation to the new value. The <code>useAnimatedStyle</code> hook automatically re-runs, updating the transform with the new scale value.</p>
<h3 id="heading-gesture-animations">Gesture Animations</h3>
<p>Gestures require even tighter integration between user input and animation. The react-native-gesture-handler library provides high-performance gesture recognition that works seamlessly with Reanimated.</p>
<p>First, install the gesture handler:</p>
<pre><code class="lang-bash">npm install react-native-gesture-handler
<span class="hljs-built_in">cd</span> ios &amp;&amp; pod install &amp;&amp; <span class="hljs-built_in">cd</span> ..
</code></pre>
<p>Next, you need to wrap your app with <code>GestureHandlerRootView</code>. This component sets up the gesture handling system at the root of your application. Without it, gestures won't work. Think of it as activating the gesture system for your entire app:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { GestureHandlerRootView } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-gesture-handler'</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">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">GestureHandlerRootView</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">flex:</span> <span class="hljs-attr">1</span> }}&gt;</span>
      {/* Your app content goes here */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">GestureHandlerRootView</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now you can create gesture-driven animations. Here's a box you can drag around the screen that springs back to center when released:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Gesture, GestureDetector } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-gesture-handler'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DraggableBox</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> offsetX = useSharedValue(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> offsetY = useSharedValue(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> pan = Gesture.Pan()
    .onChange(<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      offsetX.value += event.changeX;
      offsetY.value += event.changeY;
    })
    .onEnd(<span class="hljs-function">() =&gt;</span> {
      offsetX.value = withSpring(<span class="hljs-number">0</span>);
      offsetY.value = withSpring(<span class="hljs-number">0</span>);
    });

  <span class="hljs-keyword">const</span> animatedStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">transform</span>: [
      { <span class="hljs-attr">translateX</span>: offsetX.value },
      { <span class="hljs-attr">translateY</span>: offsetY.value },
    ],
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">GestureDetector</span> <span class="hljs-attr">gesture</span>=<span class="hljs-string">{pan}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{[styles.box,</span> <span class="hljs-attr">animatedStyle</span>]} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">GestureDetector</span>&gt;</span></span>
  );
}
</code></pre>
<p>The <code>Gesture.Pan()</code> creates a pan gesture recognizer. The <code>.onChange()</code> callback fires continuously while you're dragging – <code>event.changeX</code> and <code>event.changeY</code> tell you how much the finger moved since the last frame. By adding these values to the offsets, the box follows your finger. When you lift your finger, <code>.onEnd()</code> fires and springs the box back to the center (0, 0).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762275456257/3a536406-d678-46eb-9cfe-f689428d3412.gif" alt="3a536406-d678-46eb-9cfe-f689428d3412" class="image--center mx-auto" width="295" height="640" loading="lazy"></p>
<h3 id="heading-scroll-linked-animations">Scroll-Linked Animations</h3>
<p>Another common use case for worklets is creating effects that respond to scroll position, like headers that shrink as you scroll down or parallax backgrounds.</p>
<p>Here's a header that collapses as you scroll:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ParallaxHeader</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> scrollY = useSharedValue(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> scrollHandler = useAnimatedScrollHandler({
    <span class="hljs-attr">onScroll</span>: <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      scrollY.value = event.contentOffset.y;
    },
  });

  <span class="hljs-keyword">const</span> headerStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> height = interpolate(
      scrollY.value,
      [<span class="hljs-number">0</span>, <span class="hljs-number">150</span>],
      [<span class="hljs-number">200</span>, <span class="hljs-number">60</span>],
      <span class="hljs-string">'clamp'</span>
    );

    <span class="hljs-keyword">return</span> { height };
  });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{[styles.header,</span> <span class="hljs-attr">headerStyle</span>]}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Header<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.ScrollView</span>
        <span class="hljs-attr">onScroll</span>=<span class="hljs-string">{scrollHandler}</span>
        <span class="hljs-attr">scrollEventThrottle</span>=<span class="hljs-string">{16}</span>
      &gt;</span>
        {/* Content */}
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.ScrollView</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>The <code>useAnimatedScrollHandler</code> creates a scroll event handler that runs on the UI thread. Every time you scroll, it updates <code>scrollY</code> with the current scroll position. The <code>interpolate</code> function maps the scroll position to the header height – when scrollY is 0 (top of the scroll), height is 200. When scrollY reaches 150, height is 60. The 'clamp' option prevents the height from going outside this range.</p>
<p>With these fundamentals of CSS animations and worklets covered, let's look at how to apply them to common real-world scenarios.</p>
<h2 id="heading-real-world-patterns">Real-World Patterns</h2>
<p>Now that you understand both CSS animations and worklets, let's combine them to build three patterns you'll frequently encounter in production apps. These examples demonstrate when to use each animation approach and how to structure your code for maintainability.</p>
<p>In this section, you'll learn how to build a collapsing header that shrinks as users scroll (using worklets for scroll tracking), a bottom sheet that responds to drag gestures (using worklets for gesture control), and a swipe-to-delete interaction for list items (combining worklets for gesture detection with animations for the deletion effect).</p>
<h3 id="heading-collapsing-header">Collapsing Header</h3>
<p>A collapsing header is a navigation bar that starts tall and shrinks as you scroll down. This pattern is popular because it maximizes content space while keeping navigation accessible. You'll use worklets here because the animation needs to follow the scroll position in real-time.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CollapsibleHeader</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> scrollY = useSharedValue(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> HEADER_MAX = <span class="hljs-number">200</span>;
  <span class="hljs-keyword">const</span> HEADER_MIN = <span class="hljs-number">60</span>;

  <span class="hljs-keyword">const</span> scrollHandler = useAnimatedScrollHandler({
    <span class="hljs-attr">onScroll</span>: <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      scrollY.value = event.contentOffset.y;
    },
  });

  <span class="hljs-keyword">const</span> headerStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">height</span>: interpolate(
      scrollY.value,
      [<span class="hljs-number">0</span>, HEADER_MAX - HEADER_MIN],
      [HEADER_MAX, HEADER_MIN],
      <span class="hljs-string">'clamp'</span>
    ),
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">flex:</span> <span class="hljs-attr">1</span> }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{[styles.header,</span> <span class="hljs-attr">headerStyle</span>]}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>My App<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.ScrollView</span>
        <span class="hljs-attr">onScroll</span>=<span class="hljs-string">{scrollHandler}</span>
        <span class="hljs-attr">scrollEventThrottle</span>=<span class="hljs-string">{16}</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">height:</span> <span class="hljs-attr">1000</span>, <span class="hljs-attr">padding:</span> <span class="hljs-attr">16</span> }}&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Scroll to see header collapse<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.ScrollView</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
  );
}
</code></pre>
<p>This pattern tracks scroll position in <code>scrollY</code> and uses <code>interpolate</code> to map it to header height. When you're at the top (scrollY = 0), the header is 200 pixels tall. As you scroll down 140 pixels, the header shrinks to 60 pixels. The animation happens on every frame as you scroll, which is why worklets are necessary – CSS animations couldn't track scroll position this smoothly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762326945758/044ca9d6-dd6e-4891-b9f4-3a4dc8590b58.gif" alt="044ca9d6-dd6e-4891-b9f4-3a4dc8590b58" class="image--center mx-auto" width="295" height="640" loading="lazy"></p>
<h3 id="heading-bottom-sheet">Bottom Sheet</h3>
<p>A bottom sheet is a panel that slides up from the bottom of the screen, commonly used for action menus, filters, or additional content. Users can drag it to different heights or dismiss it with a swipe down. This requires worklets because it needs frame-by-frame gesture tracking.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">BottomSheet</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">const</span> translateY = useSharedValue(<span class="hljs-number">300</span>);
  <span class="hljs-keyword">const</span> context = useSharedValue({ <span class="hljs-attr">y</span>: <span class="hljs-number">0</span> });

  <span class="hljs-keyword">const</span> pan = Gesture.Pan()
    .onStart(<span class="hljs-function">() =&gt;</span> {
      context.value = { <span class="hljs-attr">y</span>: translateY.value };
    })
    .onChange(<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      translateY.value = <span class="hljs-built_in">Math</span>.max(
        event.translationY + context.value.y,
        <span class="hljs-number">-300</span>
      );
    })
    .onEnd(<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (event.velocityY &gt; <span class="hljs-number">500</span>) {
        translateY.value = withSpring(<span class="hljs-number">300</span>); <span class="hljs-comment">// Dismiss</span>
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (translateY.value &gt; <span class="hljs-number">-100</span>) {
        translateY.value = withSpring(<span class="hljs-number">-50</span>); <span class="hljs-comment">// Collapsed</span>
      } <span class="hljs-keyword">else</span> {
        translateY.value = withSpring(<span class="hljs-number">-300</span>); <span class="hljs-comment">// Expanded</span>
      }
    });

  <span class="hljs-keyword">const</span> animatedStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">transform</span>: [{ <span class="hljs-attr">translateY</span>: translateY.value }],
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">GestureDetector</span> <span class="hljs-attr">gesture</span>=<span class="hljs-string">{pan}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{[styles.bottomSheet,</span> <span class="hljs-attr">animatedStyle</span>]}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.handle}</span> /&gt;</span>
        {children}
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">GestureDetector</span>&gt;</span></span>
  );
}
</code></pre>
<p>The bottom sheet starts off-screen at translateY = 300. When you start dragging, <code>.onStart()</code> saves the starting position in <code>context</code>. As you drag, <code>.onChange()</code> updates the position, but <code>Math.max()</code> prevents it from going below -300 (fully expanded). When you release, <code>.onEnd()</code> checks the velocity – if you swiped down quickly (velocity &gt; 500), it dismisses. Otherwise, it snaps to either the collapsed (-50) or expanded (-300) position based on where you released it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763051520805/dd09d10f-4d77-40a9-be9c-ef85d69be69e.gif" alt="Bottom sheet demo" class="image--center mx-auto" width="295" height="640" loading="lazy"></p>
<h3 id="heading-swipe-to-delete">Swipe to Delete</h3>
<p>Swipe-to-delete lets users remove items from a list by swiping left. It's a common pattern in email apps and to-do lists. This uses worklets for gesture tracking and timing functions for the deletion animation.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SwipeToDelete</span>(<span class="hljs-params">{ children, onDelete }</span>) </span>{
  <span class="hljs-keyword">const</span> translateX = useSharedValue(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> itemHeight = useSharedValue(<span class="hljs-number">60</span>);

  <span class="hljs-keyword">const</span> pan = Gesture.Pan()
    .activeOffsetX([<span class="hljs-number">-10</span>, <span class="hljs-number">10</span>])
    .onChange(<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (event.translationX &lt; <span class="hljs-number">0</span>) {
        translateX.value = event.translationX;
      }
    })
    .onEnd(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">if</span> (translateX.value &lt; <span class="hljs-number">-100</span>) {
        translateX.value = withTiming(<span class="hljs-number">-500</span>, { <span class="hljs-attr">duration</span>: <span class="hljs-number">200</span> });
        itemHeight.value = withTiming(<span class="hljs-number">0</span>, { <span class="hljs-attr">duration</span>: <span class="hljs-number">200</span> }, <span class="hljs-function">() =&gt;</span> {
          runOnJS(onDelete)();
        });
      } <span class="hljs-keyword">else</span> {
        translateX.value = withSpring(<span class="hljs-number">0</span>);
      }
    });

  <span class="hljs-keyword">const</span> animatedStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
    <span class="hljs-attr">transform</span>: [{ <span class="hljs-attr">translateX</span>: translateX.value }],
    <span class="hljs-attr">height</span>: itemHeight.value,
  }));

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">GestureDetector</span> <span class="hljs-attr">gesture</span>=<span class="hljs-string">{pan}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{[styles.item,</span> <span class="hljs-attr">animatedStyle</span>]}&gt;</span>
        {children}
      <span class="hljs-tag">&lt;/<span class="hljs-name">Animated.View</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">GestureDetector</span>&gt;</span></span>
  );
}
</code></pre>
<p>The <code>.activeOffsetX([-10, 10])</code> setting means the gesture only activates after you've moved 10 pixels horizontally, preventing accidental triggers during vertical scrolling. The <code>if (event.translationX &lt; 0)</code> check ensures you can only swipe left, not right. If you swipe past -100 pixels and release, it triggers the deletion: the item slides off-screen (-500), the height collapses to 0, and <code>runOnJS</code> calls your delete function from the UI thread back to JavaScript.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763051815614/6e2c2d60-3d2e-49ec-9fb5-c17db00e9120.gif" alt="6e2c2d60-3d2e-49ec-9fb5-c17db00e9120" class="image--center mx-auto" width="295" height="640" loading="lazy"></p>
<p>These patterns demonstrate the power of combining Reanimated's animation approaches with gesture handling. Now, let's look at how to keep these animations performing smoothly.</p>
<h2 id="heading-performance-optimizations">Performance Optimizations</h2>
<p>Even though Reanimated runs on the UI thread, poorly structured animations can still drop frames. Here are four key optimizations that will keep your animations consistently smooth at 60 FPS.</p>
<h3 id="heading-memoize-animations">Memoize Animations</h3>
<p>Every time your component re-renders, any animations you create inside the render function are recreated. This wastes memory and processing time.</p>
<p>Don't do this – creating a new animation object on every render:</p>
<pre><code class="lang-javascript">{items.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">entering</span>=<span class="hljs-string">{FadeIn.duration(300)}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span> /&gt;</span></span>
))}
</code></pre>
<p>Instead, create the animation once outside the component or memoize it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fadeIn = FadeIn.duration(<span class="hljs-number">300</span>);
{items.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Animated.View</span> <span class="hljs-attr">entering</span>=<span class="hljs-string">{fadeIn}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span> /&gt;</span></span>
))}
</code></pre>
<p>By storing the animation in a constant, you create it once and reuse the same object for all items. This reduces memory allocation and garbage collection, keeping your animations smooth even with long lists.</p>
<h3 id="heading-use-usederivedvalue">Use useDerivedValue</h3>
<p>If you're doing expensive calculations inside <code>useAnimatedStyle</code>, those calculations run every frame, even if the dependencies haven't changed.</p>
<p>Don't do this – recalculating every frame:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> animatedStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
  <span class="hljs-attr">width</span>: <span class="hljs-built_in">Math</span>.min(<span class="hljs-built_in">Math</span>.max(offset.value * <span class="hljs-number">2</span>, <span class="hljs-number">100</span>), <span class="hljs-number">500</span>),
}));
</code></pre>
<p>Instead, use <code>useDerivedValue</code> to compute the value only when dependencies change:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> width = useDerivedValue(<span class="hljs-function">() =&gt;</span> 
  <span class="hljs-built_in">Math</span>.min(<span class="hljs-built_in">Math</span>.max(offset.value * <span class="hljs-number">2</span>, <span class="hljs-number">100</span>), <span class="hljs-number">500</span>)
);

<span class="hljs-keyword">const</span> animatedStyle = useAnimatedStyle(<span class="hljs-function">() =&gt;</span> ({
  <span class="hljs-attr">width</span>: width.value,
}));
</code></pre>
<p>Now the complex calculation only runs when <code>offset.value</code> changes, not on every frame. The <code>useAnimatedStyle</code> just reads the pre-computed width, which is much faster.</p>
<h3 id="heading-batch-updates">Batch Updates</h3>
<p>When you update multiple shared values, each update can trigger a separate re-render. This creates unnecessary work for the UI thread.</p>
<p>Don't do this – triggering multiple re-renders:</p>
<pre><code class="lang-javascript">scale.value = withSpring(<span class="hljs-number">1.2</span>);
opacity.value = withSpring(<span class="hljs-number">0.8</span>);
</code></pre>
<p>Instead, batch the updates using <code>runOnUI</code>:</p>
<pre><code class="lang-javascript">runOnUI(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-string">'worklet'</span>;
  scale.value = withSpring(<span class="hljs-number">1.2</span>);
  opacity.value = withSpring(<span class="hljs-number">0.8</span>);
})();
</code></pre>
<p>The <code>runOnUI</code> function ensures both updates happen in the same frame, so the UI only re-renders once. This is especially important when updating many values at once, like in complex gestures or choreographed animations.</p>
<h3 id="heading-prefer-transform-over-layout">Prefer Transform Over Layout</h3>
<p>Animating layout properties like width, height, or margins forces React Native to recalculate the position of every element that depends on the changing element. This is expensive.</p>
<p>Don't do this – expensive layout recalculation:</p>
<pre><code class="lang-javascript">width: withSpring(newWidth)
</code></pre>
<p>Instead, use transform properties, which only affect the visual appearance without triggering layout:</p>
<pre><code class="lang-javascript">transform: [{ <span class="hljs-attr">scaleX</span>: withSpring(scale) }]
</code></pre>
<p>Transform operations are hardware-accelerated and don't affect layout, making them dramatically faster. Whenever possible, use <code>translateX/Y</code> instead of changing position, <code>scale</code> instead of changing size, and <code>rotate</code> instead of changing orientation.</p>
<p>These optimizations will keep your animations buttery smooth. Now let's look at how to debug issues when they arise.</p>
<h2 id="heading-debugging-tips">Debugging Tips</h2>
<p>Even with proper setup, you may encounter issues with animations. Here are the most common problems and their solutions, written as complete troubleshooting steps.</p>
<h3 id="heading-animations-not-working">Animations Not Working</h3>
<p>If your animations aren't running at all, the most common cause is a missing or incorrectly configured Babel plugin. Open your <code>babel.config.js</code> file and verify that <code>react-native-worklets/plugin</code> is present in the plugins array and is the last plugin in the list. The order matters because the worklets plugin needs to process your code after all other transformations.</p>
<p>After confirming the plugin is correctly configured, clear your Metro bundler cache by running <code>npm start -- --reset-cache</code>, then rebuild your app completely. Simply reloading JavaScript won't work because Babel transformations happen during the build process.</p>
<h3 id="heading-app-crashes-on-startup-or-reload">App Crashes on Startup or Reload</h3>
<p>If your app crashes immediately after installing Reanimated or when you reload, the native modules likely aren't properly linked. With React Native 0.76+, this usually means the pods weren't installed or the native build is out of sync.</p>
<p>For iOS, run <code>cd ios &amp;&amp; pod install &amp;&amp; cd ..</code> then do a clean build with <code>npx react-native run-ios</code>. For Android, clean the build with <code>cd android &amp;&amp; ./gradlew clean &amp;&amp; cd ..</code> then rebuild with <code>npx react-native run-android</code>.</p>
<p>If you're getting build errors about missing headers or modules, make sure you've added both <code>react-native-reanimated</code> and <code>react-native-worklets</code> to your package.json dependencies.</p>
<h3 id="heading-turbomoduleregistry-not-found">"TurboModuleRegistry Not Found"</h3>
<p>If you see an error message saying "TurboModuleRegistry.get('NativeReanimated'): 'NativeReanimated' could not be found", it means the native code hasn't been properly linked to your JavaScript code.</p>
<p>First, verify you're using React Native 0.76 or newer, as Reanimated 4 requires the New Architecture. Check your <code>ios/Podfile</code> for <code>ENV['RCT_NEW_ARCH_ENABLED'] = '1'</code> and <code>android/gradle.properties</code> for <code>newArchEnabled=true</code>.</p>
<p>Then rebuild completely: <code>cd ios &amp;&amp; pod install &amp;&amp; cd .. &amp;&amp; npx react-native run-ios</code>.</p>
<h3 id="heading-logging-and-inspecting-shared-values">Logging and Inspecting Shared Values</h3>
<p>If you try to debug worklets using <code>console.log()</code>, you'll notice nothing appears in your console. This is because worklets run on the UI thread, which doesn't have direct access to the JavaScript console.</p>
<p>To log values from worklets, use the <code>useDerivedValue</code> hook:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> offset = useSharedValue(<span class="hljs-number">0</span>);

useDerivedValue(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Offset:'</span>, offset.value);
  <span class="hljs-keyword">return</span> offset.value;
});
</code></pre>
<p>For more advanced debugging, React Native's built-in debugger (accessed through dev menu → "Open Debugger") now supports debugging both threads. You can set breakpoints in worklets and inspect shared values in real-time.</p>
<h3 id="heading-monitor-performance">Monitor Performance</h3>
<p>To see if your animations are actually running at 60 FPS, enable the Performance Monitor built into React Native. Shake your device (or press Cmd+D in the iOS simulator, Cmd+M in Android emulator) to open the dev menu, then select "Show Perf Monitor".</p>
<p>The monitor displays two critical numbers: JS thread FPS and UI thread FPS. Your animations run on the UI thread, so watch that number. If it stays at 60 FPS, your animations are smooth. If it drops below 60, your animations are skipping frames and will appear janky. The JS thread FPS shows whether your React code is keeping up – if this drops, it indicates issues with your component renders, not your animations.</p>
<p>For more detailed debugging information and advanced troubleshooting, check the <a target="_blank" href="https://docs.swmansion.com/react-native-reanimated/docs/guides/debugging/">official debugging guide here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763053624344/7aeffb5f-4829-4871-bd49-6e589adeb8ad.png" alt="7aeffb5f-4829-4871-bd49-6e589adeb8ad" class="image--center mx-auto" width="1176" height="1090" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Reanimated 4 gives you two powerful approaches to animation: CSS animations for simple state changes and worklets for complex, interactive animations that need real-time control.</p>
<p>Start with CSS transitions when building your next animation feature. They're simpler to write, easier to maintain, and perfect for the majority of UI animations. Reach for worklets when you need gesture control, scroll effects, or any animation that requires frame-by-frame updates.</p>
<p>The <a target="_blank" href="https://docs.swmansion.com/react-native-reanimated">official documentation</a> provides complete API references, detailed guides, and interactive examples. The <a target="_blank" href="https://github.com/software-mansion/react-native-reanimated">GitHub repository</a> includes production-ready sample code you can study and adapt.</p>
<p>Building smooth animations isn't just about technical capability – it's about creating experiences that feel responsive, intuitive, and delightful to use. Reanimated 4 makes achieving that standard straightforward, whether you're animating a simple button press or building a complex screen transition with multiple coordinated elements.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Mobile App Development with React Native ]]>
                </title>
                <description>
                    <![CDATA[ Mobile app development has become an essential skill in today’s digital landscape, and React Native is one of the leading tools for creating powerful, cross-platform mobile apps. React Native combines the best parts of React and native app developmen... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mobile-app-development-with-react-native/</link>
                <guid isPermaLink="false">6772ae6d57dd031ab1ad4671</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 30 Dec 2024 14:30:05 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735568898507/db93197c-fbed-454d-8134-49b398c4a5df.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Mobile app development has become an essential skill in today’s digital landscape, and React Native is one of the leading tools for creating powerful, cross-platform mobile apps. React Native combines the best parts of React and native app development, enabling developers to write code once and deploy it to both iOS and Android platforms. If you've ever wanted to dive into mobile development but felt overwhelmed by where to start, this comprehensive tutorial is perfect for you.</p>
<p>We just published a course on the <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> YouTube channel that will teach you all about React Native. This beginner-friendly course, created by Dave Gray, is packed with over four hours of clear, hands-on instruction. Whether you're completely new to app development or have some experience with React, this tutorial will guide you through the essentials of React Native, helping you build functional, visually appealing, and dynamic mobile apps.</p>
<h3 id="heading-what-youll-learn">What You’ll Learn</h3>
<p>The course is structured into eight chapters, each focusing on a critical aspect of React Native development. Here’s a breakdown of what you can expect:</p>
<ol>
<li><p><strong>Intro</strong><br> A quick introduction to React Native, what it is, and why it’s such a popular choice for mobile development. You’ll set up your environment and get ready to code.</p>
</li>
<li><p><strong>Chapter 1: Start Here</strong><br> This chapter introduces the basics of React Native, including setting up your development environment and understanding the fundamental building blocks of a React Native app.</p>
</li>
<li><p><strong>Chapter 2: Build an App</strong><br> Dive into building your first simple app. You’ll learn how to create components, style them, and structure your app for better readability and functionality.</p>
</li>
<li><p><strong>Chapter 3: Navigation</strong><br> Learn how to implement navigation between different screens using React Navigation. This is essential for creating multi-screen apps that feel seamless to users.</p>
</li>
<li><p><strong>Chapter 4: List Views</strong><br> Explore how to display and manage lists in React Native, an essential skill for creating dynamic and interactive user interfaces.</p>
</li>
<li><p><strong>Chapter 5: CRUD App</strong><br> Build a simple CRUD (Create, Read, Update, Delete) application. This chapter introduces you to state management and handling user input, two critical concepts in app development.</p>
</li>
<li><p><strong>Chapter 6: Data Storage</strong><br> Learn how to store and retrieve data locally, which is crucial for offline functionality and saving user preferences.</p>
</li>
<li><p><strong>Chapter 7: Dynamic Routing</strong><br> Expand your knowledge of routing by implementing dynamic routes that adapt to the user’s input or app state.</p>
</li>
<li><p><strong>Chapter 8: EAS Development Builds</strong><br> Get introduced to Expo Application Services (EAS), a powerful tool for building and deploying your React Native apps.</p>
</li>
</ol>
<h3 id="heading-why-learn-react-native">Why Learn React Native?</h3>
<p>React Native is a popular framework because it allows you to use JavaScript—a widely used programming language—to build mobile apps. This means you can transition from web development to mobile development without needing to learn a completely new language. Plus, React Native’s community and ecosystem are rich with resources, making it easier for beginners to find support and tools.</p>
<h3 id="heading-start-building-today">Start Building Today</h3>
<p>This course provides everything you need to get started with React Native, from understanding the basics to deploying your app. By the end, you’ll have built multiple projects, gaining the confidence and skills to tackle your own mobile app ideas.</p>
<p>Ready to start your mobile app development journey? Check out the full course on the <a target="_blank" href="https://www.youtube.com/watch?v=sm5Y7Vtuihg">freeCodeCamp.org YouTube channel</a> (4-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/sm5Y7Vtuihg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Mobile App Development Course with React Native, Supabase, Next.js ]]>
                </title>
                <description>
                    <![CDATA[ Mobile app development has evolved tremendously, and creating a robust, full-featured app today involves mastering both the front-end and back-end. If you're looking to build something practical, like an e-commerce platform, and want to learn the ins... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mobile-app-development-course-with-react-native-supabase-nextjs/</link>
                <guid isPermaLink="false">670fce62ee042ff16bdfd24f</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 16 Oct 2024 14:32:02 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729089105157/93e64814-1222-433c-839d-69f16fc3220b.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Mobile app development has evolved tremendously, and creating a robust, full-featured app today involves mastering both the front-end and back-end. If you're looking to build something practical, like an e-commerce platform, and want to learn the ins and outs of native mobile app development, this course has you covered. You'll be guided through the process of building a complete gadgets-selling platform, starting from the front-end design with React Native to setting up a secure back-end with Supabase, handling payments with Stripe, and even deploying the app with Next.js for the admin panel.</p>
<p>We just published a course on the <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> YouTube channel that will teach you all about developing native mobile apps using React Native, Supabase, Stripe, and Next.js. This course is designed to take you through the entire process of building a complete e-commerce platform, making it an ideal project for anyone looking to strengthen their full-stack development skills. Whether you're new to mobile development or looking to expand your knowledge, this course covers everything step by step. Alaribe Bright developed this course.</p>
<h3 id="heading-what-youll-learn">What You’ll Learn</h3>
<ol>
<li><p><strong>React Native &amp; Expo</strong>: You'll start by creating a React Native app using Expo, a powerful framework that simplifies mobile app development. You'll dive into Expo Router for managing navigation with file-based routing, build dynamic pages for product categories, and manage cart functionality using Zustand, a lightweight state management library.</p>
</li>
<li><p><strong>Supabase</strong>: This section introduces Supabase, an open-source alternative to Firebase. You'll learn to handle authentication, database management, and real-time updates. You'll implement secure user authentication, explore SQL functions, triggers, and set up row-level security for a secure back-end.</p>
</li>
<li><p><strong>Next.js for Admin Panel</strong>: The admin panel is built using Next.js, known for its server-side rendering and API capabilities. You'll learn to manage categories and products, handle role-based access, and protect routes. The panel will allow you to perform CRUD operations (Create, Read, Update, Delete) efficiently on your platform’s data.</p>
</li>
<li><p><strong>Stripe for Payments</strong>: This course will also guide you through integrating Stripe to handle payments securely. You’ll learn how to create Stripe customers, set up checkout sessions, and manage payments, all while keeping customer data safe.</p>
</li>
<li><p><strong>Push Notifications</strong>: To enhance the user experience, you'll add real-time push notifications using EAS (Expo Application Services), ensuring your app can notify users of updates like order status changes in real time.</p>
</li>
<li><p><strong>Deployment</strong>: Finally, you'll deploy your project to Vercel, ensuring your admin panel and the entire application are live and accessible. You'll also troubleshoot deployment fixes and ensure your app runs smoothly in production.</p>
</li>
</ol>
<h3 id="heading-conclusion">Conclusion</h3>
<p>By the end of this course, you'll have a fully functioning e-commerce mobile app with an admin panel, payment integration, real-time updates, and secure authentication. This project is an excellent addition to your portfolio, demonstrating your ability to handle complex, full-stack development.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/2esQdKzRUCw">the freeCodeCamp.org YouTube channel</a> (12-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/2esQdKzRUCw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Create a MacOS App with React Native ]]>
                </title>
                <description>
                    <![CDATA[ We are excited to announce the release of our latest course on the freeCodeCamp.org YouTube channel that will teach you how to use React Native to build a MacOS application. This course will guide you through the development of a fully integrated Mac... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-macos-app-with-react-native/</link>
                <guid isPermaLink="false">66c791dfba1f8664dd9a94e8</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 22 Aug 2024 19:30:39 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724355029103/aba230f3-c814-43f5-afc0-4682355a1ddd.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We are excited to announce the release of our latest course on the <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> YouTube channel that will teach you how to use React Native to build a MacOS application. This course will guide you through the development of a fully integrated MacOS application using React Native.</p>
<p>You'll learn how to create an app that allows users to search and explore books using the Google Books API, manage personal bookshelves, and even generate AI-powered summaries. By the end of this course, you'll have a comprehensive understanding of building advanced MacOS applications.</p>
<h3 id="heading-course-overview"><strong>Course Overview</strong></h3>
<p>This course, created by Brijen Makwana, provides a step-by-step guide to building a sophisticated MacOS app using React Native. You'll gain hands-on experience with essential tools and techniques, from setting up your development environment to implementing advanced features like AI-powered book summaries and state management.</p>
<p>Here are the key things you will learn:</p>
<ul>
<li><p><strong>Setup and Initialization</strong>: Begin by setting up React Native on your Mac and initializing your project. You'll learn how to clean up the project structure to ensure a smooth development process.</p>
</li>
<li><p><strong>Building Components</strong>: Develop key components such as the SearchBar and BookItem, which are crucial for user interaction and displaying book information.</p>
</li>
<li><p><strong>Integrating Google Books API</strong>: Discover how to use Postman to test the Google Books API and integrate it into your project, enabling users to search and explore a vast library of books.</p>
</li>
<li><p><strong>State Management with Tanstack Query and Zustand</strong>: Learn how to manage application state efficiently using Tanstack Query and Zustand. You'll create custom hooks like useSearch and useBook to streamline data fetching and state updates.</p>
</li>
<li><p><strong>Navigation and Routing</strong>: Implement React Navigation to ensure smooth transitions between different screens in your app. You'll add routes for the Book Screen and Bookshelves Screen, enhancing the user experience.</p>
</li>
<li><p><strong>AI-Powered Features</strong>: Explore the integration of AI by setting up Google Generative AI and creating a custom hook, useAI, to generate book summaries. This feature adds a modern touch to your app, providing users with concise and insightful book overviews.</p>
</li>
<li><p><strong>Local Storage and Book Management</strong>: Implement local storage support to save user data and manage bookshelves effectively. You'll learn how to update and remove books using Zustand, ensuring a seamless user experience.</p>
</li>
</ul>
<p>The course is structured into detailed sections, each focusing on a specific aspect of app development:</p>
<ul>
<li><p>Book Management MacOS App (React Native)</p>
</li>
<li><p>Setup React Native on your Mac</p>
</li>
<li><p>Initialize the Project</p>
</li>
<li><p>Cleanup the Project</p>
</li>
<li><p>SearchBar Component</p>
</li>
<li><p>Intro to Google Books API</p>
</li>
<li><p>Use Postman to test the API</p>
</li>
<li><p>Integrate Google Books API in the Project</p>
</li>
<li><p>Setup Tanstack Query</p>
</li>
<li><p>useSearch Custom Hook</p>
</li>
<li><p>BookItem Component</p>
</li>
<li><p>Render Books on Home Screen</p>
</li>
<li><p>Add support for Icons in the Project</p>
</li>
<li><p>Rating in BookItem</p>
</li>
<li><p>Setup React Navigation</p>
</li>
<li><p>Add new Route for Book Screen</p>
</li>
<li><p>useBook Custom Hook</p>
</li>
<li><p>Implement Book Screen</p>
</li>
<li><p>Add types to React Navigation</p>
</li>
<li><p>SelectBookShelf Component</p>
</li>
<li><p>Add new Route for Bookshelves Screen</p>
</li>
<li><p>SegmentedButtons Component</p>
</li>
<li><p>Intro to Zustand</p>
</li>
<li><p>Setup Zustand</p>
</li>
<li><p>Zustand store for Bookshelves</p>
</li>
<li><p>BookShelfItem Component</p>
</li>
<li><p>Render Books on Bookshelves Screen</p>
</li>
<li><p>Implement update book in Zustand</p>
</li>
<li><p>Implement remove book in Zustand</p>
</li>
<li><p>Implement Local Storage Support</p>
</li>
<li><p>AI Book Summary</p>
</li>
<li><p>Setup Google Generative AI</p>
</li>
<li><p>useAI Custom Hook</p>
</li>
<li><p>Outro</p>
</li>
</ul>
<h3 id="heading-join-us-today"><strong>Join Us Today</strong></h3>
<p>Head over to the <a target="_blank" href="https://youtu.be/-kizZZrh1zM">freeCodeCamp.org YouTube channel</a> to watch the course (3-hour watch). Whether you're looking to enhance your current projects or embark on new ones, this course will help you master MacOS application development.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/-kizZZrh1zM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Build a Meditation App with React Native & Expo Router ]]>
                </title>
                <description>
                    <![CDATA[ Are you looking to enhance your React Native skills while creating a practical and soothing application? This new course from freeCodeCamp.org is perfect for you! You'll learn how to build a meditation app using Expo, an open-source platform for maki... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-meditation-app-with-react-native-expo-router/</link>
                <guid isPermaLink="false">6685759dc4274328d1d57108</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 03 Jul 2024 16:00:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1720022414585/f0f87e6e-c5b4-4ea3-8ccb-d56c14e2d94f.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you looking to enhance your React Native skills while creating a practical and soothing application? This new course from <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> is perfect for you! You'll learn how to build a meditation app using Expo, an open-source platform for making universal native apps for Android, iOS, and the web with JavaScript and React. Throughout the course, you'll leverage TypeScript, React, NativeWind, and other powerful tools to develop a simple yet functional mobile app that promotes relaxation and mindfulness.</p>
<p>This comprehensive tutorial will guide you through every step of the development process, from setting up your local development environment to implementing various screens and functionalities within the app. You'll also learn how to incorporate TypeScript for type safety, use NativeWind for styling, and manage your app's navigation and state effectively.</p>
<p>Here's a glimpse of what you'll learn in this course:</p>
<h3 id="heading-introduction">Introduction</h3>
<p>You will start by understanding the fundamentals of creating a meditation app using Expo and React Native, providing a solid foundation for the rest of the project.</p>
<h3 id="heading-setup-local-development-environment">Setup Local Development Environment</h3>
<p>Learn how to set up your local development environment, including installing necessary tools and dependencies to get started with Expo and React Native.</p>
<h3 id="heading-add-static-assets-and-define-constant-files">Add Static Assets and Define Constant Files</h3>
<p>Understand how to add static assets such as images and icons to your project and define constant files for better organization and maintainability.</p>
<h3 id="heading-setup-nativewind">Setup NativeWind</h3>
<p>Explore how to set up NativeWind for styling your application components in a consistent and efficient manner.</p>
<h3 id="heading-implement-initial-screen">Implement Initial Screen</h3>
<p>Implement the initial screen of your meditation app, laying the groundwork for a smooth user experience.</p>
<h3 id="heading-splash-screen-image">Splash Screen Image</h3>
<p>Create an engaging splash screen image to enhance the visual appeal of your app during the startup phase.</p>
<h3 id="heading-the-userouter-hook">The useRouter Hook</h3>
<p>Learn to use the useRouter hook for handling navigation within your app, ensuring seamless transitions between different screens.</p>
<h3 id="heading-add-appgradient-component-and-tabs-directory">Add AppGradient Component and Tabs Directory</h3>
<p>Enhance your app's UI by adding a gradient component and organizing your tabs directory for better structure and navigation.</p>
<h3 id="heading-the-meditation-index-screen">The Meditation Index Screen</h3>
<p>Build the Meditation Index Screen, where users can browse through available meditation sessions.</p>
<h3 id="heading-use-flatlist-on-the-meditation-index-screen">Use FlatList on the Meditation Index Screen</h3>
<p>Implement FlatList to efficiently display a list of meditation sessions, ensuring a smooth scrolling experience.</p>
<h3 id="heading-the-affirmations-index-screen">The Affirmations Index Screen</h3>
<p>Create an Affirmations Index Screen, allowing users to explore various positive affirmations.</p>
<h3 id="heading-the-affirmations-detail-screen">The Affirmations Detail Screen</h3>
<p>Develop the Affirmations Detail Screen to provide more information and details about each affirmation.</p>
<h3 id="heading-the-meditation-detail-screen">The Meditation Detail Screen</h3>
<p>Implement the Meditation Detail Screen, giving users access to specific meditation session details and options.</p>
<h3 id="heading-meditation-audiosong">Meditation Audio/Song</h3>
<p>Incorporate meditation audio or songs into your app, enhancing the overall meditation experience for users.</p>
<h3 id="heading-react-context-and-modal-screen">React Context and Modal Screen</h3>
<p>Learn how to use React Context for state management and create a modal screen for additional interactive elements within your app.</p>
<p>By the end of this course, you will have built a fully functional meditation app while gaining valuable experience with Expo, React Native, TypeScript, and other essential tools. Whether you're a beginner or an experienced developer, this course offers something for everyone, helping you grow your skills and create impactful mobile applications.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/9UKCv9T_rIo">the freeCodeCamp.org YouTube channel</a> (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9UKCv9T_rIo" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Store Data Locally in React Native Expo ]]>
                </title>
                <description>
                    <![CDATA[ React Native has grown in popularity as a mobile application development tool because of its ability to create cross-platform applications using familiar JavaScript and React principles.  When building mobile applications, one common requirement is t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-store-data-locally-in-react-native-expo/</link>
                <guid isPermaLink="false">66b9ee747bae781916c2d6dd</guid>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ John Caleb ]]>
                </dc:creator>
                <pubDate>Mon, 13 May 2024 11:42:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/local-storage-in--react-native-expo--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>React Native has grown in popularity as a mobile application development tool because of its ability to create cross-platform applications using familiar JavaScript and React principles. </p>
<p>When building mobile applications, one common requirement is the ability to save data locally on the device. This is when local storage comes into play. <a target="_blank" href="https://docs.expo.dev/versions/latest/sdk/async-storage/">Async Storage</a>, provided by React Native Expo, is a simple but powerful solution for saving data locally within your React Native Expo apps.</p>
<p>In this tutorial, we'll discuss the fundamentals of local storage, introduce Async Storage, and demonstrate how to properly integrate it into React Native Expo projects.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-what-is-local-storage">What is Local Storage?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-async-storage">What is Async Storage?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-get-started-with-async-storage">How to Get Started with Async Storage</a></li>
<li><a class="post-section-overview" href="#heading-understanding-async-storage-methods">Understanding Async Storage Methods</a></li>
<li><a class="post-section-overview" href="#heading-advanced-usage-and-best-practices">Advanced Usage and Best Practices</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Familiarity with React Native and JavaScript.</li>
<li>Node.js and npm (or yarn) installed.</li>
</ul>
<h2 id="heading-what-is-local-storage">What is Local Storage?</h2>
<p>Local storage is an essential component of mobile app development, allowing developers to store data on the user's device. Unlike other storage choices such as databases, Local Storage uses a straightforward key-value pair storage technique.</p>
<p>Developers can use it to save small quantities of data that remain stored even when they close the program or restart the device. This makes it excellent for storing user preferences, authentication tokens, and other important information.</p>
<p>Local storage is essential for boosting app speed because it eliminates the need to retrieve data from faraway servers regularly.</p>
<h2 id="heading-what-is-async-storage">What is Async Storage?</h2>
<p>Async Storage is a key-value storage system supplied by React Native Expo that allows you to manage local storage in mobile apps. It provides a simple key-value storage system that enables developers to store and retrieve data asynchronously. </p>
<p>Unlike synchronous storage methods, Async Storage allows you to save and retrieve data without interrupting the main thread, resulting in a more seamless user experience.</p>
<h2 id="heading-how-to-get-started-with-async-storage">How to Get Started with Async Storage</h2>
<p>To use Async Storage in your React Native Expo project, ensure that Expo is installed. If you haven't already set up a React Native Expo project, you can do so by installing Expo CLI:</p>
<pre><code class="lang-bash">$ npm install -g expo-cli
</code></pre>
<p>Create a new Expo project:</p>
<pre><code class="lang-bash">$ expo init MyProject
$ <span class="hljs-built_in">cd</span> MyProject
</code></pre>
<p>To add Async Storage to your project, run the following command:</p>
<pre><code class="lang-js">$ expo install @react-native-<span class="hljs-keyword">async</span>-storage/<span class="hljs-keyword">async</span>-storage
</code></pre>
<p>The <code>@react-native-async-storage/async-storage</code> is a community-maintained version of AsyncStorage. Once installed, you can then setup a file to handle the AsyncStorage methods such as <code>setItem()</code>, <code>updateItem()</code>, <code>deleteItem()</code>, and others. This file would be imported whenever you want to make a call to the local storage. </p>
<p>In this example, we'll create a folder named <code>utils</code> in the root path of our project and then create the <code>AsyncStorage.js</code> file to handle these methods:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/-4611C08C-3557-460A-A7CC-BFD754BD13F7-.png.jpg" alt="Async Storage File Structure " width="600" height="400" loading="lazy">
<em>Async Storage File Structure</em></p>
<p>Within the <code>AsyncStorage.js</code> file, you can define the AsyncStorage methods like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// utils/AsyncStorage.js</span>

<span class="hljs-keyword">import</span> AsyncStorage <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-native-async-storage/async-storage'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> setItem = <span class="hljs-keyword">async</span> (key, value) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> AsyncStorage.setItem(key, <span class="hljs-built_in">JSON</span>.stringify(value));
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error setting item:'</span>, error);
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getItem = <span class="hljs-keyword">async</span> (key) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> value = <span class="hljs-keyword">await</span> AsyncStorage.getItem(key);
    <span class="hljs-keyword">return</span> value != <span class="hljs-literal">null</span> ? <span class="hljs-built_in">JSON</span>.parse(value) : <span class="hljs-literal">null</span>;
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error getting item:'</span>, error);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> removeItem = <span class="hljs-keyword">async</span> (key) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> AsyncStorage.removeItem(key);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error removing item:'</span>, error);
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> mergeItem = <span class="hljs-keyword">async</span> (key, value) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> AsyncStorage.mergeItem(key, <span class="hljs-built_in">JSON</span>.stringify(value));
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error merging item:'</span>, error);
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> clear = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> AsyncStorage.clear();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error clearing AsyncStorage:'</span>, error);
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getAllKeys = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> AsyncStorage.getAllKeys();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error getting all keys:'</span>, error);
    <span class="hljs-keyword">return</span> [];
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getAllItems = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> keys = <span class="hljs-keyword">await</span> AsyncStorage.getAllKeys();
    <span class="hljs-keyword">const</span> items = <span class="hljs-keyword">await</span> AsyncStorage.multiGet(keys);
    <span class="hljs-keyword">return</span> items.reduce(<span class="hljs-function">(<span class="hljs-params">accumulator, [key, value]</span>) =&gt;</span> {
      accumulator[key] = <span class="hljs-built_in">JSON</span>.parse(value);
      <span class="hljs-keyword">return</span> accumulator;
    }, {});
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error getting all items:'</span>, error);
    <span class="hljs-keyword">return</span> {};
  }
};
</code></pre>
<p>Moving forward, In the next section, we'll explain and break down the meaning of these AsyncStorage functions in the AsyncStorage.js file.</p>
<h2 id="heading-understanding-async-storage-methods">Understanding Async Storage Methods</h2>
<p>By separating AsyncStorage functions into their own file, you can conveniently manage and reuse them throughout your React Native Expo project. This modular approach improves code maintenance and readability.</p>
<p>In the previous section, we created the <code>AsyncStorage.js</code> file and added several functions. </p>
<p>In the following sections, we'll talk about these methods and how to use them effectively.</p>
<h3 id="heading-setitem"><code>setItem()</code></h3>
<p>This method is essential for storing data locally on the device. It allows developers to store key-value pairs in AsyncStorage, where the key serves as a unique identifier and the value represents the data to be stored.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.setItem(<span class="hljs-string">'username'</span>, <span class="hljs-string">'freeCodeCamp'</span>);
</code></pre>
<h3 id="heading-getitem"><code>getItem()</code></h3>
<p>The <code>getItem()</code> method returns the value associated with a given key from local storage. It sends a parameter/key, which is the unique identification of the data being requested. And it returns the value associated with the supplied key, or null if no value is discovered for the given key.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> username = <span class="hljs-keyword">await</span> AsyncStorage.getItem(<span class="hljs-string">'username'</span>);
</code></pre>
<p>In this scenario, the value for the key <code>username</code> is fetched from local storage. This obtained value, <code>freeCodeCamp</code>, is then placed in the variable username, making it available for further use across the application.</p>
<h3 id="heading-removeitem"><code>removeItem()</code></h3>
<p>This function deletes the object with the supplied key from local storage. It's useful when you want to remove a specific piece of data that's no longer required.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.removeItem(<span class="hljs-string">'username'</span>);
</code></pre>
<p>In this example, the object identified by the key <code>username</code> is removed from local storage.</p>
<h3 id="heading-mergeitem"><code>mergeItem()</code></h3>
<p>The <code>mergeItem()</code> method combines the value of an existing key with the value supplied as input. If the key do not exists, it works similarly to <code>setItem()</code>, creating a new key-value pair.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.mergeItem(<span class="hljs-string">'user'</span>, <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span> }));
</code></pre>
<h3 id="heading-clear"><code>clear()</code></h3>
<p>The <code>clear()</code> method deletes all items from local storage. It's useful when you wish to delete all local data, such as when you log out of a user or reset the application state.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.clear();
</code></pre>
<h3 id="heading-getallkeys"><code>getAllKeys()</code></h3>
<p>The <code>getAllKeys()</code> function returns all keys kept in local storage. It's useful when you need to loop through all keys or conduct operations based on the keys in local storage.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> keys = <span class="hljs-keyword">await</span> AsyncStorage.getAllKeys();
</code></pre>
<h3 id="heading-multiget"><code>multiGet()</code></h3>
<p>The <code>multiGet()</code> function obtains several key-value pairs from local storage using an array of keys provided.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> AsyncStorage.multiGet([<span class="hljs-string">'username'</span>, <span class="hljs-string">'email'</span>]);
</code></pre>
<p>In this example, the values for the keys <code>username</code> and <code>email</code> are fetched from local storage.</p>
<h2 id="heading-advanced-usage-and-best-practices">Advanced Usage and Best Practices</h2>
<p>While AsyncStorage provides a straightforward interface for local storage, there are several best practices to consider:</p>
<ol>
<li><strong>Data Serialization</strong>: When storing complex data types such as objects or arrays, remember to serialize them into a string format using <code>JSON.stringify()</code> before storing and deserialize them using <code>JSON.parse()</code> when retrieving.</li>
<li><strong>Error Handling</strong>: Implement robust error handling to gracefully handle any failures that may occur during Async Storage operations.</li>
<li><strong>Security Considerations</strong>: Be mindful of the sensitivity of the data being stored locally and implement appropriate security measures such as encryption for sensitive information.</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, using local storage into your React Native Expo projects is essential for developing robust and responsive mobile applications. Async Storage simplifies the process of storing and retrieving data on the device, providing a consistent user experience and enabling offline functionalities. </p>
<p>By following the steps provided in this article, you can utilize Async Storage to improve your apps local storage functionality.</p>
<p>Remember, if you have any questions or just want to say hi, feel free to reach me on <a target="_blank" href="https://twitter.com/thejohncaleb">X(Twitter)</a> or my <a target="_blank" href="https://thejohncaleb.netlify.app/contact">website</a>. :)  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a React Native Splash Screen ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you'll get a hands-on practical guide for creating a native splash screen for React Native CLI applications.  Note that this tutorial is not applicable for apps created with Expo. SVG Icon Image and Background The first thing you nee... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-native-splash-screen/</link>
                <guid isPermaLink="false">66ba2d7cde9370f66eeb0a95</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Lucas ]]>
                </dc:creator>
                <pubDate>Wed, 08 May 2024 19:17:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/article-1-rnsplash-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you'll get a hands-on practical guide for creating a native splash screen for React Native CLI applications. </p>
<p>Note that this tutorial is not applicable for apps created with Expo.</p>
<h2 id="heading-svg-icon-image-and-background">SVG Icon Image and Background</h2>
<p>The first thing you need is an image. It can be in any format, but I recommend using SVG because, from it, you will generate icons of various sizes for different types of Android and iOS devices.</p>
<p>You will also need a background color that complements or contrasts your project's primary color. In my case, I will use #074C4E.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/nubble-logo.png" alt="Image" width="600" height="400" loading="lazy">
<em>icon imagem and backgorund color</em></p>
<h2 id="heading-add-the-image-to-the-project">Add the Image to the Project</h2>
<p>Next, add the SVG image to your project. It doesn't matter where. The most important thing is remembering the path because you will need to reference it later. </p>
<p>In my case, I placed it in <code>src/assets/svgs/logo-vertical-white.svg</code>.</p>
<h2 id="heading-how-to-use-the-react-native-bootsplash-library">How to Use the react-native-bootsplash Library</h2>
<p>You will use the <code>[react-native-bootsplash](https://github.com/zoontek/react-native-bootsplash)</code>  library to create native splash screens. This library will help you in three essential areas to guarantee your users an excellent experience when encountering the splash screen.</p>
<ol>
<li><strong>Native Splash Screens</strong>: React Native apps have a "JavaScript side" that only loads after the native side is ready. Therefore, to present a splash screen quickly, a native experience is necessary. The good news is that all the code is already inside the library, so you just need to connect it to your project.</li>
<li><strong>Generation of Images and Files</strong>: When creating native splash screens, it is necessary to create specific image files for each platform. This can be done through tools like Xcode and Android Studio. Fortunately, the library comes with a CLI (command-line interface) that allows you to generate these files with just one command!</li>
<li><strong>Hide at the Right Moment</strong>: In many cases, even after the native side has loaded, the app may still not be ready to display content to the user. On the JavaScript side, you still need to load your navigation stack, fetch the user's authentication status, or call the API to fetch some data. With the <code>react-native-bootsplash</code>, you can choose when to hide the splash screen.</li>
</ol>
<p>First, let's add the library. As I am using Yarn as my dependency manager, I will execute the command:</p>
<pre><code class="lang-bash">yarn add react-native-bootsplash
</code></pre>
<p>Since the library has native dependencies, you need to install the pods on the iOS side. Inside the <code>ios</code> folder, run the following command:</p>
<pre><code class="lang-bash">pod install
</code></pre>
<p>Great, the library installation is complete 😁. In case you're wondering, the native Android dependencies are automatically installed when you run the <code>yarn android</code> command. We'll do this later after finishing the setup.</p>
<h2 id="heading-how-to-generate-the-splash-screen-files">How to Generate the Splash Screen Files</h2>
<p>In addition to installing the library, you need to generate the files and images mentioned earlier and update a few native files after that.</p>
<p>The <code>react-native-bootsplash</code> has a command that helps us create all the necessary native files and images to create a native Android and iOS splash screen.</p>
<p>It's worth mentioning that the library also has a premium option, where you can buy a license key to unlock extra CLI commands, like adding more than one icon on the screen and generating different images for Dark Mode. You will use the simplest splash screen, so you don't need a license key. But I highly recommend it if you have any of the use cases mentioned above and also to support the library's author, who does an incredible job.</p>
<p>To generate the files, you'll need the following to run the command, which you should customize according to your project:</p>
<ol>
<li>File path and name: <code>src/assets/svgs/logo-vertica-white.svg</code></li>
<li>The background color: <code>074C4E</code></li>
<li>The logo width: <code>105</code></li>
</ol>
<pre><code class="lang-bash">yarn react-native generate-bootsplash src/assets/svgs/logo-vertica-white.svg \\
   --platforms=android,ios \\
   --background=074C4E \\
   --logo-width=105
</code></pre>
<p>After running this command, you will see that the native image files, color, and storyboard have been successfully generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/terminal.png" alt="Image" width="600" height="400" loading="lazy">
<em>terminal output</em></p>
<h2 id="heading-how-to-connect-the-library-to-the-project">How to Connect the Library to the Project</h2>
<p>It is time to integrate the library and newly created splash screen with the project by modifying some native files.</p>
<h3 id="heading-ios-appdelegatemm">iOS - AppDelegate.mm</h3>
<p>On iOS, the file where you configure libraries with native dependencies is the <strong>AppDelegate.mm</strong>. </p>
<p>And you will do this in two steps. First, import the library at the top of the file:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#import <span class="hljs-meta-string">"RNBootSplash.h"</span></span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/ios-import.png" alt="Image" width="600" height="400" loading="lazy">
<em>importing BootSplash on AppDelegate</em></p>
<p>The second change in this file is to add the function that will connect the native and JavaScript sides. Add this snippet at the end of the project before the last <code>@end</code>. The code will be different if you use a react-native version below 0.74.</p>
<pre><code class="lang-cpp"><span class="hljs-comment">// ⬇️ Add this before file @end (for react-native 0.74+)</span>
- (<span class="hljs-keyword">void</span>)customizeRootView:(RCTRootView *)rootView {
  [RNBootSplash initWithStoryboard:@<span class="hljs-string">"BootSplash"</span> rootView:rootView]; <span class="hljs-comment">// ⬅️ initialize the splash screen</span>
}

<span class="hljs-comment">// OR</span>

<span class="hljs-comment">// ⬇️ Add this before file @end (for react-native &lt; 0.74)</span>
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
                          moduleName:(NSString *)moduleName
                           initProps:(NSDictionary *)initProps {
  UIView *rootView = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
  [RNBootSplash initWithStoryboard:@<span class="hljs-string">"BootSplash"</span> rootView:rootView]; <span class="hljs-comment">// ⬅️ initialize the splash screen</span>
  <span class="hljs-keyword">return</span> rootView;
}
</code></pre>
<p>In my case, I am on react-native 0.73, so my modification looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/ios-code.png" alt="Image" width="600" height="400" loading="lazy">
<em>added createRootViewWithBridge (react-native &lt; 0.74)</em></p>
<h3 id="heading-android-stylesxml">Android - styles.xml</h3>
<p>On Android, you need to change three native files. Let's start with <strong>styles.xml</strong>.</p>
<p>Inside the <strong>android/app/src/main/res/values/styles.xml</strong> file, add the following code snippet inside the <code>resources</code> tag. Remember, there is already a <code>style</code> tag within it – do not replace it. Add an extra one.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"BootTheme"</span> <span class="hljs-attr">parent</span>=<span class="hljs-string">"Theme.BootSplash"</span>&gt;</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">item</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"bootSplashBackground"</span>&gt;</span>@color/bootsplash_background<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">item</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"bootSplashLogo"</span>&gt;</span>@drawable/bootsplash_logo<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">item</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"postBootSplashTheme"</span>&gt;</span>@style/AppTheme<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/android-styles.png" alt="Image" width="600" height="400" loading="lazy">
<em>styles.xml</em></p>
<h3 id="heading-android-androidmanifestxml">Android - AndroidManifest.xml</h3>
<p>To connect the splash screen in the file <strong>android/app/src/main/AndroidManifest.xml</strong>, you have to add the property <code>android:theme="@style/BootTheme"</code> inside the <code>activity</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/android-AndroidManifest.png" alt="Image" width="600" height="400" loading="lazy">
<em>My AndroidManifest.xml</em></p>
<h3 id="heading-android-modify-the-mainactivityjavakt">Android - Modify the MainActivity.java/kt</h3>
<p>You need to initiate the splash screen within the <code>MainActivity</code>. Depending on your version of React Native, your file may have a Java or Kotlin extension. You have to modify or create the <code>onCreate</code> method if it does not exist.</p>
<p>I literally copied the code below from the library <strong>README</strong> file, so you don't need to jump there but feel free to check it <a target="_blank" href="https://github.com/zoontek/react-native-bootsplash?tab=readme-ov-file#android-1">here</a>.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Java (react-native &lt; 0.73)</span>
<span class="hljs-comment">// …</span>

<span class="hljs-comment">// add these required imports:</span>
<span class="hljs-keyword">import</span> android.os.Bundle;
<span class="hljs-keyword">import</span> com.zoontek.rnbootsplash.RNBootSplash;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ReactActivity</span> </span>{

  <span class="hljs-comment">// …</span>

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{
    RNBootSplash.init(<span class="hljs-keyword">this</span>, R.style.BootTheme); <span class="hljs-comment">// ⬅️ initialize the splash screen</span>
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); <span class="hljs-comment">// super.onCreate(null) with react-native-screens</span>
  }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/android-MainActivity.png" alt="Image" width="600" height="400" loading="lazy">
<em>My final MainActivity.java</em></p>
<h3 id="heading-hide-the-splash-screen">Hide the Splash Screen</h3>
<p>The implementation is ready for both platforms! But before running the app, you must hide the splash screen at some point on the JavaScript side; otherwise, the app will open and get stuck.</p>
<p>Of course, where to put it depends significantly on what you need to load for your app to be ready to display to the user. A classic example is waiting for React Navigation to load the navigation stack, which is signaled through the <code>onReady</code> callback.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> BootSplash <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native-bootsplash'</span>;
<span class="hljs-comment">// ...</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Router</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// ...</span>
    <span class="hljs-keyword">return</span> (
    &lt;NavigationContainer onReady={<span class="hljs-function">() =&gt;</span> BootSplash.hide({fade: <span class="hljs-literal">true</span>})}&gt;
      {Stack}
    &lt;/NavigationContainer&gt;
  );
}
</code></pre>
<h3 id="heading-you-are-ready-to-go">You are ready to go!</h3>
<p>Your splash screen is ready for use! However, since you modified native files, rebuilding the app is necessary. To do this, run the commands <code>yarn ios</code> and <code>yarn android</code> to see how your implementation works.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/showcase.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Thanks for reading! If you speak Portuguese and would like more content about React Native, subscribe to my YouTube channel <a target="_blank" href="https://www.youtube.com/@Coffstack">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Mobile Quiz App with React Native, ChatGPT and Supabase ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you'll learn how to build a mobile quiz application that authenticates users, allows them to take tests, and ranks them based on their scores.  The application leverages some of Supabase's features, such as authentication and databa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-mobile-quiz-app/</link>
                <guid isPermaLink="false">66b8fc7a33470f39c663c1a4</guid>
                
                    <category>
                        <![CDATA[ chatgpt ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ supabase ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Asaolu ]]>
                </dc:creator>
                <pubDate>Thu, 29 Feb 2024 17:30:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/Building-a-mobile-quiz-app-with-React-Native--ChatGPT-and-Supabase--1--1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you'll learn how to build a mobile quiz application that authenticates users, allows them to take tests, and ranks them based on their scores. </p>
<p>The application leverages some of Supabase's features, such as authentication and database storage, to build a secured full-stack mobile application.</p>
<p>Additionally, you'll learn how to create React Native applications with Expo, generate a set of questions and answers from ChatGPT, and perform CRUD operations and user authentication with Supabase.</p>
<p>To fully understand this tutorial, you'll need to have a basic knowledge of React Native and data fetching in React applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-mobile-application-demo">Mobile Application Demo</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-react-native-application-with-expo-1">How to set up a React Native application with Expo</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-react-native-application-with-expo-1">How to style the React Native application with Tailwind CSS</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-application-screens">How to build the application screens</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-authentication-screens">How to build the authentication screens</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-tab-screens">How to build the tab screens</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-stack-screens">How to build the stack screens</a></li>
<li><a class="post-section-overview" href="#heading-how-to-generate-quiz-questions-and-answers-from-chatgpt">How to generate quiz questions and answers from ChatGPT</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-supabase-to-react-native">How to add Supabase to React Native</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-supabase-authentication-to-react-native-applications">How to add Supabase authentication to React Native applications</a></li>
<li><a class="post-section-overview" href="#heading-how-to-sign-up-new-users">How to sign up new users</a></li>
<li><a class="post-section-overview" href="#heading-how-to-sign-in-existing-users">How to sign in existing users</a></li>
<li><a class="post-section-overview" href="#heading-how-to-log-users-out-of-the-application">How to log users out of the application</a></li>
<li><a class="post-section-overview" href="#heading-how-to-protect-screens-from-unauthenticated-users">How to protect screens from unauthenticated users</a></li>
<li><a class="post-section-overview" href="#heading-how-to-interact-with-the-supabase-database">How to interact with the Supabase database</a></li>
<li><a class="post-section-overview" href="#heading-how-to-save-the-users-score-to-the-database">How to save user's score to the database</a></li>
<li><a class="post-section-overview" href="#heading-how-to-retrieve-data-from-supabase">How to retrieve data from Supabase</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-mobile-application-demo">Mobile Application Demo</h2>
<p>To preview the application, download <a target="_blank" href="https://expo.dev/client">Expo Go</a> and paste the links below into the app URL field:</p>
<p><strong>Android:</strong> <code>exp://u.expo.dev/update/a4774250-e156-4d34-bcfc-a4f2549c2e1d</code><br><strong>iOS:</strong> <code>exp://u.expo.dev/update/7e5f8ba5-89c4-4c1d-b219-a613ace642df</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/app-demo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Scan the QR code to preview the mobile quiz application within the Expo Go application</em></p>
<h2 id="heading-how-to-set-up-a-react-native-application-with-expo">How to Set Up a React Native Application with Expo</h2>
<p>Expo is an open-source platform that allows you to create cross-platform applications easily with JavaScript. It saves us from the complex configurations required to create a native application with the React Native CLI, making it the easiest and fastest way to build and publish React Native apps.</p>
<p>Execute the code snippet below to create a new <a target="_blank" href="https://expo.dev/">Expo</a> project that uses <a target="_blank" href="https://docs.expo.dev/router/introduction/">Expo Router</a> for navigating between screens.</p>
<pre><code class="lang-bash">npx create-expo-app@latest --template tabs@50
</code></pre>
<p><a target="_blank" href="https://docs.expo.dev/router/introduction/">Expo Router</a> is an open-source file-based routing system that enables users to navigate between screens easily. It is similar to Next.js, where each file name represents its route name.</p>
<p>Start the development server to ensure that the app is working as expected.</p>
<pre><code class="lang-bash">npx expo start
</code></pre>
<h3 id="heading-how-to-style-the-react-native-application-with-tailwind-css">How to style the React Native application with Tailwind CSS</h3>
<p>Tailwind CSS is a CSS framework that lets you create modern and stunning applications easily. </p>
<p>However, to style Expo applications using Tailwind CSS, you need to install <a target="_blank" href="https://www.nativewind.dev/v4/getting-started/expo-router">NativeWind</a> – a library that uses Tailwind CSS as its scripting language.</p>
<p>Run the code snippet below to install NativeWind and its dependencies:</p>
<pre><code class="lang-bash">npx expo install nativewind@^4.0.1 react-native-reanimated tailwindcss
</code></pre>
<p>Execute <code>npx tailwindcss init</code> within your terminal to create a <code>tailwind.config.js</code> file. Update the file with the code snippet below:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-attr">content</span>: [<span class="hljs-string">"./app/**/*.{js,jsx,ts,tsx}"</span>],
    <span class="hljs-attr">presets</span>: [<span class="hljs-built_in">require</span>(<span class="hljs-string">"nativewind/preset"</span>)],
    <span class="hljs-attr">theme</span>: {
        <span class="hljs-attr">extend</span>: {},
    },
    <span class="hljs-attr">plugins</span>: [],
};
</code></pre>
<p>Create a <code>globals.css</code> file within the root of your project and add the Tailwind directives below:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> components;
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<p>Update the <code>babel.config.js</code> file with the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">api</span>) </span>{
  api.cache(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">presets</span>: [
      [<span class="hljs-string">"babel-preset-expo"</span>, { <span class="hljs-attr">jsxImportSource</span>: <span class="hljs-string">"nativewind"</span> }],
      <span class="hljs-string">"nativewind/babel"</span>,
    ],
  };
};
</code></pre>
<p>Create a <code>metro.config.js</code> file within the root of your project and paste the code snippet below into the file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { getDefaultConfig } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"expo/metro-config"</span>);
<span class="hljs-keyword">const</span> { withNativeWind } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'nativewind/metro'</span>);

<span class="hljs-keyword">const</span> config = getDefaultConfig(__dirname)

<span class="hljs-built_in">module</span>.exports = withNativeWind(config, { <span class="hljs-attr">input</span>: <span class="hljs-string">'./globals.css'</span> })
</code></pre>
<p>Finally, import the <code>./globals.css</code> file into the <code>app/_layout.tsx</code> file to enable you to style your application with Tailwind CSS:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//👉🏻 Within ./app/_layout.tsx</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"../globals.css"</span>;
</code></pre>
<p>Great job on creating the React Native project with Expo! Now, you're ready to add some style using Tailwind CSS. If you encounter any problems while installing NativeWind, check out the <a target="_blank" href="https://www.nativewind.dev/v4/getting-started/expo-router">documentation</a> for a step-by-step guide.</p>
<h2 id="heading-how-to-build-the-application-screens">How to Build the Application Screens</h2>
<p>Here, I'll guide you through building the application screens. They are divided into three categories:</p>
<ul>
<li>The Authentication screens – the register and login screens.</li>
<li>The Tab layout screens – the dashboard, leaderboard, and profile screens.</li>
<li>The Stack screens – the test and test completion screens.</li>
</ul>
<p>The application prompts new users to create an account and log in before allowing access to the Tab layout screens. </p>
<p>On the dashboard screen, users can take tests on various topics. The leaderboard screen showcases the top ten users. Users can log out or preview their previous attempts on the profile page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/application-demo.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Application Demo</em></p>
<h3 id="heading-how-to-build-the-authentication-screens">How to Build the Authentication Screens</h3>
<p>The authentication screens accept the user's email and password and ensure the credentials are valid before creating an account or granting access to the application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/auth-screens.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Authentication Screens</em></p>
<p>Create an <code>index.tsx</code> and a <code>register.tsx</code> file within the <code>app</code> folder and a component that accepts the user's email and password using the <a target="_blank" href="https://reactnative.dev/docs/textinput">React Native TextInput</a> component.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Text, View, TextInput, Pressable, Alert } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> { Link, useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-router"</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</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">LoginScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [email, setEmail] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">""</span>);
    <span class="hljs-keyword">const</span> [password, setPassword] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">""</span>);
    <span class="hljs-keyword">const</span> [loading, setLoading] = useState&lt;<span class="hljs-built_in">boolean</span>&gt;(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> router = useRouter();

    <span class="hljs-comment">//👇🏻 triggered when the user submits the email &amp; password</span>
    <span class="hljs-keyword">const</span> handleLogin = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (!email.trim() || !password.trim())
            <span class="hljs-keyword">return</span> Alert.alert(<span class="hljs-string">"Error"</span>, <span class="hljs-string">"Please fill in all fields"</span>);
        setLoading(<span class="hljs-literal">true</span>);
        <span class="hljs-built_in">console</span>.log({
            email,
            password,
        });
        router.replace(<span class="hljs-string">"/(tabs)/"</span>);
    };

    <span class="hljs-keyword">return</span> (
        &lt;View&gt;
        {<span class="hljs-comment">/** -- user interface--*/</span>}
        &lt;/View&gt;
    );
}
</code></pre>
<p>The code snippet stores the user's email and password in states using the React useState hook. The <code>handleLogin</code> function accepts the user's email and password when the form is submitted and ensures that they are not empty before logging them to the console and redirecting the user to the Dashboard page.</p>
<p>You can create the user interface using the code snippet below. It displays the input fields for the user's credentials and an interactive Sign-in button that executes the <code>handleLogin</code> function. Additionally, the <code>loading</code> state ensures that the button is only pressed once.</p>
<pre><code class="lang-typescript">&lt;View className=<span class="hljs-string">' flex-1'</span>&gt;
    &lt;View className=<span class="hljs-string">'w-full px-4'</span>&gt;
        &lt;Text className=<span class="hljs-string">'text-3xl mb-4 font-bold text-white text-center'</span>&gt;
            Log <span class="hljs-keyword">in</span>
        &lt;/Text&gt;

        &lt;Text className=<span class="hljs-string">'text-lg text-gray-200'</span>&gt;Email Address&lt;/Text&gt;
        &lt;TextInput
            className=<span class="hljs-string">'w-full border-b-[1px] py-4 rounded-md mb-3 text-white font-bold'</span>
            value={email}
            onChangeText={setEmail}
        /&gt;
        &lt;Text className=<span class="hljs-string">'text-lg text-gray-200'</span>&gt;Password&lt;/Text&gt;
        &lt;TextInput
            className=<span class="hljs-string">'w-full border-b-[1px] py-4 rounded-md mb-3 text-white font-bold'</span>
            secureTextEntry
            value={password}
            onChangeText={setPassword}
        /&gt;
        &lt;Pressable
            className={<span class="hljs-string">`w-full <span class="hljs-subst">${
                loading ? <span class="hljs-string">"bg-orange-200"</span> : <span class="hljs-string">"bg-orange-600"</span>
            }</span> rounded-xl p-4 border-[1px] border-orange-200`</span>}
            disabled={loading}
            onPress={<span class="hljs-function">() =&gt;</span> handleLogin()}
        &gt;
            &lt;Text className=<span class="hljs-string">'text-white text-center font-bold text-xl'</span>&gt;
                {loading ? <span class="hljs-string">"Authenticating..."</span> : <span class="hljs-string">"Sign in"</span>}
            &lt;/Text&gt;
        &lt;/Pressable&gt;
        &lt;Text className=<span class="hljs-string">'text-center mt-2 text-orange-200'</span>&gt;
            Don<span class="hljs-string">'t have an account?{" "}
            &lt;Link href='</span>/register<span class="hljs-string">'&gt;
                &lt;Text className='</span>text-white<span class="hljs-string">'&gt;Register&lt;/Text&gt;
            &lt;/Link&gt;
        &lt;/Text&gt;
    &lt;/View&gt;
&lt;/View&gt;</span>
</code></pre>
<p>For instance, the <code>loading</code> state becomes true when a user clicks the Sign-in button. The Pressable component (button) has a <code>disabled</code> attribute set to the <code>loading</code> state to ensure that the user does not press the button multiple times. Additionally, you can use the loading state to notify the user that the request is processing.</p>
<p>The <code>register.tsx</code> file is also similar to the <code>login.tsx</code> file. You only need to change the words from Login to Register.</p>
<h3 id="heading-how-to-build-the-tab-screens">How to Build the Tab Screens</h3>
<p>The Tab Screens consist of the Dashboard, Leaderboard, and Profile screens.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/tab-screens.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Tab Screens</em></p>
<p>Create a <code>(tabs)</code> folder containing <code>index.tsx</code>, <code>leaderboard.tsx</code>, <code>profile.tsx</code>, and <code>_layout.tsx</code> files within the <code>app</code> folder.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> app
mkdir (tabs)
<span class="hljs-built_in">cd</span> (tabs)
touch index.tsx leaderboard.tsx profile.tsx _layout.tsx
</code></pre>
<p>After creating the <code>_layout.tsx</code> file within the (tabs) folder, update the <code>_layout.tsx</code> to specify Tab screen navigation for the newly created screens. The screens use icons from the <a target="_blank" href="https://icons.expo.fyi/Index">Expo Vector Icons library</a>.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Tabs } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-router"</span>;
<span class="hljs-keyword">import</span> { Ionicons, MaterialIcons, FontAwesome5 } <span class="hljs-keyword">from</span> <span class="hljs-string">"@expo/vector-icons"</span>;
<span class="hljs-keyword">import</span> { ActivityIndicator } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</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">TabScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        &lt;Tabs
            screenOptions={{
                tabBarActiveTintColor: <span class="hljs-string">"#f97316"</span>,
                tabBarInactiveTintColor: <span class="hljs-string">"gray"</span>,
                tabBarShowLabel: <span class="hljs-literal">false</span>,
                headerShown: <span class="hljs-literal">false</span>,
                tabBarStyle: {
                    backgroundColor: <span class="hljs-string">"#ffedd5"</span>,
                    borderTopColor: <span class="hljs-string">"#ffedd5"</span>,
                },
            }}
        &gt;
            &lt;Tabs.Screen
                name=<span class="hljs-string">'index'</span>
                options={{
                    tabBarIcon: <span class="hljs-function">(<span class="hljs-params">{ color }</span>) =&gt;</span> (
                        &lt;Ionicons name=<span class="hljs-string">'home'</span> size={<span class="hljs-number">24</span>} color={color} /&gt;
                    ),
                }}
            /&gt;
            &lt;Tabs.Screen
                name=<span class="hljs-string">'leaderboard'</span>
                options={{
                    tabBarIcon: <span class="hljs-function">(<span class="hljs-params">{ color }</span>) =&gt;</span> (
                        &lt;MaterialIcons name=<span class="hljs-string">'leaderboard'</span> size={<span class="hljs-number">24</span>} color={color} /&gt;
                    ),
                }}
            /&gt;
            &lt;Tabs.Screen
                name=<span class="hljs-string">'profile'</span>
                options={{
                    tabBarIcon: <span class="hljs-function">(<span class="hljs-params">{ color }</span>) =&gt;</span> (
                        &lt;FontAwesome5 name=<span class="hljs-string">'user-alt'</span> size={<span class="hljs-number">24</span>} color={color} /&gt;
                    ),
                }}
            /&gt;
        &lt;/Tabs&gt;
    );
}
</code></pre>
<p>Next, update the <code>RootLayoutNav</code> component within the <code>_app/layout.tsx</code> file to render all the screens within the application.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RootLayoutNav</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        &lt;Stack screenOptions={{ headerShown: <span class="hljs-literal">false</span> }}&gt;
            &lt;Stack.Screen name=<span class="hljs-string">'(tabs)'</span> /&gt;
            &lt;Stack.Screen name=<span class="hljs-string">'(stack)'</span> /&gt;
            &lt;Stack.Screen name=<span class="hljs-string">'index'</span> /&gt;
            &lt;Stack.Screen name=<span class="hljs-string">'register'</span> /&gt;
        &lt;/Stack&gt;
    );
}
</code></pre>
<h4 id="heading-the-dashboard-screen">The Dashboard Screen</h4>
<p>Update the component to allow users to select four categories from a list of categories.</p>
<pre><code class="lang-typescript"><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">HomeScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> greet = getGreeting();
    <span class="hljs-keyword">const</span> router = useRouter();
    <span class="hljs-keyword">const</span> { session } = useAuth();
    <span class="hljs-keyword">const</span> [loading, setLoading] = useState&lt;<span class="hljs-built_in">boolean</span>&gt;(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [userCategories, setUserCategories] = useState&lt;<span class="hljs-built_in">string</span>[]&gt;([]);

    <span class="hljs-keyword">const</span> fetchQuestions = <span class="hljs-keyword">async</span> () =&gt; {};

    <span class="hljs-keyword">const</span> handleStartTest = <span class="hljs-keyword">async</span> () =&gt; {
        Alert.alert(<span class="hljs-string">"Start Test"</span>, <span class="hljs-string">"Are you sure you want to start the test?"</span>, [
            {
                text: <span class="hljs-string">"Cancel"</span>,
                style: <span class="hljs-string">"destructive"</span>,
            },
            {
                text: <span class="hljs-string">"Yes"</span>,
                onPress: <span class="hljs-function">() =&gt;</span> fetchQuestions(),
            },
        ]);
    };

    <span class="hljs-keyword">return</span> (
        &lt;SafeAreaView className=<span class="hljs-string">'flex-1 bg-orange-100 px-4 py-2'</span>&gt;
            &lt;View className=<span class="hljs-string">'flex flex-row items-center justify-between mb-2'</span>&gt;
                &lt;View&gt;
                    &lt;Text className=<span class="hljs-string">'font-bold text-2xl mb-[1px]'</span>&gt;
                        Good morning
                        &lt;Ionicons name=<span class="hljs-string">'partly-sunny-sharp'</span> size={<span class="hljs-number">24</span>} color=<span class="hljs-string">'orange'</span> /&gt;
                    &lt;/Text&gt;

                    &lt;Text className=<span class="hljs-string">'text-lg'</span>&gt;Welcome User&lt;/Text&gt;
                &lt;/View&gt;
            &lt;/View&gt;
            {userCategories.length === <span class="hljs-number">4</span> &amp;&amp; (
                &lt;Pressable
                    className={<span class="hljs-string">`w-full h-[70px] flex items-center justify-center <span class="hljs-subst">${
                        loading ? <span class="hljs-string">"bg-orange-300"</span> : <span class="hljs-string">"bg-orange-500"</span>
                    }</span> rounded-xl mb-2`</span>}
                    disabled={loading}
                    onPress={<span class="hljs-function">() =&gt;</span> handleStartTest()}
                &gt;
                    &lt;Text className=<span class="hljs-string">'text-xl font-bold text-orange-50'</span>&gt;
                        {loading ? <span class="hljs-string">"Loading questions..."</span> : <span class="hljs-string">"START TEST"</span>}
                    &lt;/Text&gt;
                &lt;/Pressable&gt;
            )}

            &lt;View className=<span class="hljs-string">'w-full flex-1'</span>&gt;
                &lt;Text className=<span class="hljs-string">'text-xl font-bold text-orange-500 mb-4'</span>&gt;
                    Available Categories
                &lt;/Text&gt;
                &lt;FlatList
                    data={categories}
                    numColumns={<span class="hljs-number">2</span>}
                    contentContainerStyle={{ width: <span class="hljs-string">"100%"</span>, gap: <span class="hljs-number">10</span> }}
                    columnWrapperStyle={{ gap: <span class="hljs-number">10</span> }}
                    renderItem={<span class="hljs-function">(<span class="hljs-params">{ item }</span>) =&gt;</span> (
                        &lt;Categories
                            item={item}
                            userCategories={userCategories}
                            setUserCategories={setUserCategories}
                        /&gt;
                    )}
                    showsVerticalScrollIndicator={<span class="hljs-literal">false</span>}
                    keyExtractor={<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id}
                /&gt;
            &lt;/View&gt;
        &lt;/SafeAreaView&gt;
    );
}
</code></pre>
<p>The code snippet above renders a list of categories where users can select only four categories to answer questions on and start the quiz.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/dashboard-screen.gif" alt="Image" width="600" height="400" loading="lazy">
<em>The Dashboard Screen</em></p>
<h4 id="heading-the-leaderboard-screen">The Leaderboard Screen</h4>
<p>The Leaderboard screen displays the top ten users ranked in descending order.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Text, FlatList, SafeAreaView } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> Board <span class="hljs-keyword">from</span> <span class="hljs-string">"../../components/Board"</span>;

<span class="hljs-keyword">interface</span> Props {
    total_score: <span class="hljs-built_in">number</span>;
    user_id: <span class="hljs-built_in">string</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">LeaderboardScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [leaderboard, setLeaderboard] = useState&lt;Props[]&gt;([]);

    <span class="hljs-keyword">return</span> (
        &lt;SafeAreaView className=<span class="hljs-string">'flex-1 bg-orange-100 p-4'</span>&gt;
            &lt;Text className=<span class="hljs-string">'text-2xl font-bold text-gray-500 text-center mb-6'</span>&gt;
                Leaderboard
            &lt;/Text&gt;

            &lt;FlatList
                data={leaderboard}
                renderItem={<span class="hljs-function">(<span class="hljs-params">{ item }</span>) =&gt;</span> &lt;Board item={item} /&gt;}
                keyExtractor={<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.user_id}
                showsVerticalScrollIndicator={<span class="hljs-literal">false</span>}
            /&gt;
        &lt;/SafeAreaView&gt;
    );
}
</code></pre>
<p>The code snippet above renders a FlatList with ten items. You can create an array containing ten users and pass it into the FlatList for now.</p>
<h4 id="heading-the-profile-screen">The Profile Screen</h4>
<p>The Profile Screen displays the user's image, recent attempts, and a log-out button that enables the user to sign out of the application.</p>
<pre><code class="lang-typescript"><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">ProfileScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [loading, setLoading] = useState&lt;<span class="hljs-built_in">boolean</span>&gt;(<span class="hljs-literal">false</span>);
    <span class="hljs-keyword">const</span> [total_score, setTotalScore] = useState&lt;<span class="hljs-built_in">number</span>&gt;(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">const</span> [attempts, setAttempts] = useState&lt;<span class="hljs-built_in">string</span>[]&gt;([]);

    <span class="hljs-keyword">const</span> handleSignOut = <span class="hljs-keyword">async</span> () =&gt; {
        setLoading(<span class="hljs-literal">true</span>);
    };

    <span class="hljs-keyword">return</span> (
        &lt;SafeAreaView className=<span class="hljs-string">'flex-1 bg-orange-100 p-4'</span>&gt;
            &lt;View className=<span class="hljs-string">'flex items-center justify-center mb-6'</span>&gt;
                &lt;Text className=<span class="hljs-string">'text-gray-600 mb-[1px]'</span>&gt;
                    &lt;FontAwesome name=<span class="hljs-string">'star'</span> size={<span class="hljs-number">20</span>} color=<span class="hljs-string">'red'</span> /&gt;
                    &lt;Text&gt;<span class="hljs-number">45</span>&lt;/Text&gt;
                &lt;/Text&gt;
                &lt;Text className=<span class="hljs-string">'text-gray-600 mb-2'</span>&gt;<span class="hljs-meta">@dhastix</span>&lt;/Text&gt;

                &lt;Pressable onPress={<span class="hljs-function">() =&gt;</span> handleSignOut()} disabled={loading}&gt;
                    &lt;Text className=<span class="hljs-string">'text-red-500'</span>&gt;
                        {loading ? <span class="hljs-string">"Logging out..."</span> : <span class="hljs-string">"Log out"</span>}
                    &lt;/Text&gt;
                &lt;/Pressable&gt;
            &lt;/View&gt;

            &lt;Text className=<span class="hljs-string">'font-bold text-xl text-gray-700 mb-3 px-4'</span>&gt;
                Recent Attempts
            &lt;/Text&gt;

            &lt;FlatList
                data={attempts}
                contentContainerStyle={{ padding: <span class="hljs-number">15</span> }}
                renderItem={<span class="hljs-function">(<span class="hljs-params">{ item }</span>) =&gt;</span> &lt;Attempts item={item} /&gt;}
                keyExtractor={<span class="hljs-function">(<span class="hljs-params">item, index</span>) =&gt;</span> index.toString()}
                showsVerticalScrollIndicator={<span class="hljs-literal">false</span>}
            /&gt;
        &lt;/SafeAreaView&gt;
    );
}
</code></pre>
<p>The code snippet above displays the user's image, the sign-out button, and all the user's attempts. You can create an array of items for testing purposes.</p>
<h3 id="heading-how-to-build-the-stack-screens">How to Build the Stack Screens</h3>
<p>The Stack Screens comprise two screens – the quiz screen and the screen that displays the user's score after completing a quiz session.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/test-screens-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Stack Screens</em></p>
<h4 id="heading-the-quiz-screen">The Quiz Screen</h4>
<p>The Quiz Screen displays a timer that countdowns from 15 seconds before moving to the next question. It shows the question, its category, available options, the Skip and Next buttons, and a cancel icon.</p>
<p>Create a similar screen to the one shown below. You can use <a target="_blank" href="https://github.com/dha-stix/techtest-app/blob/main/app/(stack)/test.tsx">this</a> as a guide.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/test-screen.gif" alt="Image" width="600" height="400" loading="lazy">
<em>The Quiz Screen</em></p>
<h4 id="heading-the-quiz-completion-screen">The Quiz Completion Screen</h4>
<p>It displays the user's score after completing a test.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {
    SafeAreaView,
    Text,
    Pressable,
    View,
    ImageBackground,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> { MaterialIcons } <span class="hljs-keyword">from</span> <span class="hljs-string">"@expo/vector-icons"</span>;
<span class="hljs-keyword">import</span> { useLocalSearchParams } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-router"</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">CompletedScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> { score } = useLocalSearchParams();

    <span class="hljs-keyword">return</span> (
        &lt;View className=<span class="hljs-string">'flex flex-1 bg-orange-400'</span>&gt;
            &lt;ImageBackground
                source={{ uri: <span class="hljs-string">"https://source.unsplash.com/NAP14GEjvh8"</span> }}
                className=<span class="hljs-string">'flex-1 p-4'</span>
            &gt;
                &lt;SafeAreaView /&gt;
                &lt;Pressable onPress={<span class="hljs-function">() =&gt;</span> router.replace(<span class="hljs-string">"/(tabs)/"</span>)}&gt;
                    &lt;MaterialIcons name=<span class="hljs-string">'cancel'</span> size={<span class="hljs-number">60</span>} color=<span class="hljs-string">'white'</span> /&gt;
                &lt;/Pressable&gt;

                &lt;View className=<span class="hljs-string">'flex-1 flex items-center justify-center'</span>&gt;
                    &lt;View className=<span class="hljs-string">'bg-orange-50 w-full py-[50px] rounded-xl p-4 flex items-center justify-center shadow-lg shadow-orange-500'</span>&gt;
                        &lt;Text className=<span class="hljs-string">'text-3xl text-orange-600 font-bold mb-4'</span>&gt;
                            {<span class="hljs-built_in">Number</span>(score) &gt; <span class="hljs-number">20</span> ? <span class="hljs-string">"Congratulations🥳"</span> : <span class="hljs-string">"Sorry! You lose 🥲"</span>}
                        &lt;/Text&gt;
                        &lt;Text className=<span class="hljs-string">'font-bold text-xl'</span>&gt;You scored {score}!&lt;/Text&gt;
                    &lt;/View&gt;
                &lt;/View&gt;
            &lt;/ImageBackground&gt;
        &lt;/View&gt;
    );
}
</code></pre>
<p>The code snippet above accepts the user's score as a parameter after completing the quiz and displays the score to the user.</p>
<h2 id="heading-how-to-generate-quiz-questions-and-answers-from-chatgpt">How to Generate Quiz Questions and Answers from ChatGPT</h2>
<p>When building a quiz application, the first question is: how do you get the questions and options for the application? You can either create a list of questions or search for a suitable public API.</p>
<p>However, I'll guide you through creating a list of questions and options in JSON format using ChatGPT. Use this prompt to generate questions and answers from ChatGPT:</p>
<blockquote>
<p><em>Generate 25 distinct questions on  and ensure they are in JSON format containing an id, category which is , a question attribute containing the question, an options array of 3 options, and an answer property.</em></p>
</blockquote>
<p>The prompt returns a JSON result containing the questions and answers. You can host them on GitHub or save them to a database.</p>
<p>The questions and answers I'm using in this mobile application are available on <a target="_blank" href="https://github.com/dha-stix/trivia-app/tree/main/questions">GitHub</a>. Feel free to clone or copy the files.</p>
<p>Once your questions and answers are ready, you can connect the application to Supabase.</p>
<h2 id="heading-how-to-add-supabase-to-react-native">How to Add Supabase to React Native</h2>
<p>Supabase is an open-source Firebase alternative that enables you to create secured and scalable software applications within a few minutes.</p>
<p>It provides a secured Postgres database, a complete user management system that handles various forms of authentication (including email and password, email sign-in, and social authentication), a file storage system that lets you store and serve files of any size, real-time communication, and many other features.</p>
<p>In this tutorial, I'll walk you through the following:</p>
<ul>
<li>How to authenticate users and control access to some application screens with Supabase.</li>
<li>How to save the users' scores to the database to enable you to rank them based on their scores.</li>
</ul>
<p>First, you need to install Supabase and its required dependencies. You can do that with the following commands:</p>
<pre><code class="lang-bash">npm install @supabase/supabase-js 
npm install react-native-elements @react-native-async-storage/async-storage react-native-url-polyfill
npx expo install expo-secure-store
</code></pre>
<p>Create a <code>supabase.ts</code> file within your project and copy the code snippet below into the file to initiate Supabase:</p>
<pre><code class="lang-typescript"><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> SecureStore <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-secure-store"</span>;
<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">const</span> ExpoSecureStoreAdapter = {
    getItem: <span class="hljs-function">(<span class="hljs-params">key: <span class="hljs-built_in">string</span></span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> SecureStore.getItemAsync(key);
    },
    setItem: <span class="hljs-function">(<span class="hljs-params">key: <span class="hljs-built_in">string</span>, value: <span class="hljs-built_in">string</span></span>) =&gt;</span> {
        SecureStore.setItemAsync(key, value);
    },
    removeItem: <span class="hljs-function">(<span class="hljs-params">key: <span class="hljs-built_in">string</span></span>) =&gt;</span> {
        SecureStore.deleteItemAsync(key);
    },
};

<span class="hljs-keyword">const</span> supabaseUrl = <span class="hljs-string">"YOUR_REACT_NATIVE_SUPABASE_URL"</span>;
<span class="hljs-keyword">const</span> supabaseAnonKey = <span class="hljs-string">"YOUR_REACT_NATIVE_SUPABASE_ANON_KEY"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> supabase = createClient(supabaseUrl, supabaseAnonKey, {
    auth: {
        storage: ExpoSecureStoreAdapter <span class="hljs-keyword">as</span> <span class="hljs-built_in">any</span>,
        autoRefreshToken: <span class="hljs-literal">true</span>,
        persistSession: <span class="hljs-literal">true</span>,
        detectSessionInUrl: <span class="hljs-literal">false</span>,
    },
});
</code></pre>
<p>Next, visit the <a target="_blank" href="https://supabase.com">Supabase homepage</a>, sign in, and create a new organization and project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new Supabase project</em></p>
<p>Click the Settings icon on the sidebar and select API to copy the project URL and the public API key.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-24-at-17.50.34.png" alt="Image" width="600" height="400" loading="lazy">
<em>Supabase API settings containing project credentials</em></p>
<p>Create a <code>.env.local</code> file and copy the credentials into the variables. Update the <code>supabase.ts</code> file to use the Supabase URL and API key.</p>
<pre><code class="lang-txt">EXPO_PUBLIC_API_URL=&lt;YOUR_SUPABASE_URL&gt;
EXPO_PUBLIC_API_KEY=&lt;YOUR_SUPABASE_API_KEY&gt;
</code></pre>
<p>Congratulations! You can now interact with Supabase from your application and access various features such as authentication, database, file storage, and so on.</p>
<h2 id="heading-how-to-add-supabase-authentication-to-react-native-applications">How to Add Supabase Authentication to React Native Applications</h2>
<p>Supabase offers various forms of authentication. But we only need the email and password method of authentication for this application.</p>
<h3 id="heading-how-to-sign-up-new-users">How to sign up new users</h3>
<p>The code snippet below accepts an email and a password and creates an account for the user. Otherwise, it returns an error if any of the credentials is invalid.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//👇🏻 import supabase from supabase file</span>
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../lib/supabase"</span>;

<span class="hljs-comment">//👇🏻 sign up function</span>
<span class="hljs-keyword">const</span> handleRegister = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">if</span> (!email.trim() || !password.trim())
        <span class="hljs-keyword">return</span> Alert.alert(<span class="hljs-string">"Error"</span>, <span class="hljs-string">"Please fill in all fields"</span>);
    <span class="hljs-keyword">const</span> { error } = <span class="hljs-keyword">await</span> supabase.auth.signUp({ email, password });
    <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> Alert.alert(<span class="hljs-string">"Error"</span>, error.message);
    router.replace(<span class="hljs-string">"/"</span>);
};
</code></pre>
<p>With the <code>supabase.auth.signUp()</code> function, Supabase handles the authentication process. If successful, the user is redirected to the login page. Otherwise, it displays an error message.</p>
<h3 id="heading-how-to-sign-in-existing-users">How to sign in existing users</h3>
<p>This function allows existing users to access the application. It accepts the user's email and password and logs the user into the application.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//👇🏻 import supabase from supabase file</span>
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../lib/supabase"</span>;

<span class="hljs-comment">//👇🏻 register function</span>
<span class="hljs-keyword">const</span> handleLogin = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">if</span> (!email.trim() || !password.trim())
        <span class="hljs-keyword">return</span> Alert.alert(<span class="hljs-string">"Error"</span>, <span class="hljs-string">"Please fill in all fields"</span>);
    <span class="hljs-keyword">const</span> { error } = <span class="hljs-keyword">await</span> supabase.auth.signInWithPassword({ email, password });
    <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> Alert.alert(<span class="hljs-string">"Error"</span>, error.message);
    router.replace(<span class="hljs-string">"/(tabs)/"</span>);
};
</code></pre>
<p>The <code>supabase.auth.signInWithPassword()</code> function validates the user's email and password and redirects the user to the Dashboard screen. Otherwise, it returns the necessary authentication error.</p>
<h3 id="heading-how-to-log-users-out-of-the-application">How to log users out of the application</h3>
<p>Supabase also allows users to sign out of the application. You can execute this function when the user clicks a button within the Profile page.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//👇🏻 import supabase from supabase file</span>
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../lib/supabase"</span>;

<span class="hljs-comment">//👇🏻 sign out function</span>
<span class="hljs-keyword">const</span> handleSignOut = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { error } = <span class="hljs-keyword">await</span> supabase.auth.signOut();
        <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
    }
};
</code></pre>
<h3 id="heading-how-to-protect-screens-from-unauthenticated-users">How to protect screens from unauthenticated users</h3>
<p>You've been able to add the sign-up, sign-in, and log-out functionalities to the React Native application. But the Dashboard and other screens containing sensitive data are still accessible to unauthenticated users.</p>
<p>How do we fix this?</p>
<p>In this section, I'll walk you through how to protect screens from unauthorized users using the <a target="_blank" href="https://react.dev/reference/react/createContext">React Context API</a>.</p>
<p>The React Context API allows us to pass data through the component tree without needing to pass props down manually at every level.</p>
<p>Create an <code>AuthProvider.tsx</code> file. This is where the data to be passed down the application screens is stored. Copy the code snippet below into the file:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"./supabase"</span>;
<span class="hljs-keyword">import</span> { Session } <span class="hljs-keyword">from</span> <span class="hljs-string">"@supabase/supabase-js"</span>;
<span class="hljs-keyword">import</span> {
    PropsWithChildren,
    createContext,
    useContext,
    useEffect,
    useState,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">type</span> AuthData = {
    session: Session | <span class="hljs-literal">null</span>;
    loading: <span class="hljs-built_in">boolean</span>;
};

<span class="hljs-comment">//👇🏻 data to be passed down the components</span>
<span class="hljs-keyword">const</span> AuthContext = createContext&lt;AuthData&gt;({
    session: <span class="hljs-literal">null</span>,
    loading: <span class="hljs-literal">true</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">AuthProvider</span>(<span class="hljs-params">{ children }: PropsWithChildren</span>) </span>{
    <span class="hljs-keyword">const</span> [session, setSession] = useState&lt;Session | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>);

    <span class="hljs-comment">//👇🏻 fetches the current user's session</span>
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> fetchSession = <span class="hljs-keyword">async</span> () =&gt; {
            <span class="hljs-keyword">const</span> {
                data: { session },
            } = <span class="hljs-keyword">await</span> supabase.auth.getSession();
            setSession(session);
            setLoading(<span class="hljs-literal">false</span>);
        };

        fetchSession();
        supabase.auth.onAuthStateChange(<span class="hljs-function">(<span class="hljs-params">_event, session</span>) =&gt;</span> {
            setSession(session);
            setLoading(<span class="hljs-literal">false</span>);
        });
    }, []);

    <span class="hljs-keyword">return</span> (
        &lt;AuthContext.Provider value={{ session, loading }}&gt;
            {children}
        &lt;/AuthContext.Provider&gt;
    );
}
<span class="hljs-comment">//👇🏻 custom hook for using the context (data)</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> useAuth = <span class="hljs-function">() =&gt;</span> useContext(AuthContext);
</code></pre>
<p>The code snippet retrieves the current user's session. If the user is signed in, the session and loading state variables are updated to show that the user is active, and they are passed into other components within the application.</p>
<p>The <code>useAuth</code> custom hook allows you to access the state variables (session and loading) within the application screens.</p>
<p>To access the context (data) available within the application screens, wrap the entire application with the <code>AuthProvider</code>. So now, update the <code>RootLayoutNav</code> component within the <code>app/_layout.tsx</code> file as shown below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> AuthProvider <span class="hljs-keyword">from</span> <span class="hljs-string">"../lib/AuthProvider"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">RootLayoutNav</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        &lt;AuthProvider&gt;
            &lt;Stack screenOptions={{ headerShown: <span class="hljs-literal">false</span> }}&gt;
                &lt;Stack.Screen name=<span class="hljs-string">'(tabs)'</span> /&gt;
                &lt;Stack.Screen name=<span class="hljs-string">'(stack)'</span> /&gt;
                &lt;Stack.Screen name=<span class="hljs-string">'index'</span> /&gt;
                &lt;Stack.Screen name=<span class="hljs-string">'register'</span> /&gt;
            &lt;/Stack&gt;
        &lt;/AuthProvider&gt;
    );
}
</code></pre>
<p>Congratulations! You've successfully set up the context. Next, how do we read the context and ensure that only authenticated users can view some of the application screens?</p>
<p>You can do this using the custom <code>useAuth</code> hook. For example, you can protect the Tabs screens via the <code>(tabs)/_layout.tsx</code> file.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Tabs, Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-router"</span>;
<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../lib/AuthProvider"</span>;
<span class="hljs-keyword">import</span> { ActivityIndicator } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</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">TabScreen</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> { session, loading } = useAuth();

    <span class="hljs-keyword">if</span> (!session) {
        <span class="hljs-keyword">return</span> &lt;Redirect href=<span class="hljs-string">'/'</span> /&gt;;
    }

    <span class="hljs-keyword">if</span> (loading) {
        <span class="hljs-keyword">return</span> &lt;ActivityIndicator size=<span class="hljs-string">'large'</span> color=<span class="hljs-string">'#f97316'</span> /&gt;;
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> (
            &lt;Tabs
                screenOptions={{
                    tabBarActiveTintColor: <span class="hljs-string">"#f97316"</span>,
                    tabBarInactiveTintColor: <span class="hljs-string">"gray"</span>,
                    tabBarShowLabel: <span class="hljs-literal">false</span>,
                    headerShown: <span class="hljs-literal">false</span>,
                    tabBarStyle: {
                        backgroundColor: <span class="hljs-string">"#ffedd5"</span>,
                        borderTopColor: <span class="hljs-string">"#ffedd5"</span>,
                    },
                }}
            &gt;
                {<span class="hljs-comment">/**-- screens--*/</span>}
            &lt;/Tabs&gt;
        );
    }
}
</code></pre>
<p>The code snippet above checks if there is a session for the current user. If null, the application redirects the user to the login screen. If the application is yet to determine the user's status, it displays a loading icon.</p>
<h2 id="heading-how-to-interact-with-the-supabase-database">How to Interact with the Supabase Database</h2>
<p>In this section, I'll walk you through creating the database for the mobile application. You'll learn how to store and retrieve the user's scores and rank them based on their total score.</p>
<p>Before we proceed, note that the application calculates the user's score after answering each question on the test screen. Upon completion, the user's score is retrieved and displayed on the test completion screen.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> handleSave = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//👇🏻 checks if the user has not completed the test</span>
    <span class="hljs-keyword">if</span> (count &lt; questions.length - <span class="hljs-number">1</span>) {
        <span class="hljs-comment">//👇🏻 updates the user's score if the selected answer is correct</span>
        <span class="hljs-keyword">if</span> (questions[count].answer === userAnswer) {
            setUserScore(<span class="hljs-function">(<span class="hljs-params">userScore</span>) =&gt;</span> userScore + <span class="hljs-number">1</span>);
        }
        <span class="hljs-comment">//👇🏻 change the question, refresh the selected answer and time</span>
        setCount(<span class="hljs-function">(<span class="hljs-params">count</span>) =&gt;</span> count + <span class="hljs-number">1</span>);
        setSelectedBox(<span class="hljs-literal">null</span>);
        setTime(<span class="hljs-number">15</span>);
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">//👇🏻 test completed</span>
        router.push({
            pathname: <span class="hljs-string">"/(stack)/completed"</span>,
            params: { score: userScore },
        });
    }
};
</code></pre>
<p>Within your Supabase project, select Table Editor from the sidebar menu and create a new table containing the following columns:</p>
<ul>
<li><code>id</code> – contains a unique ID for each row of data.</li>
<li><code>created_at</code> – represents the time the data was created.</li>
<li><code>attempts</code> – a text array containing the score and date attributes.</li>
<li><code>total_score</code> – represents a user's cumulative score. We'll rank users using this score</li>
<li><code>user_id</code> – a unique ID used to identify each user's data.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-24-at-10.05.55.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Table Columns</em></p>
<p>Finally, you can add a Row Level Security that allows only authenticated users interact with the database.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-24-at-10.20.51.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Table Row Level Security Policy</em></p>
<h3 id="heading-how-to-save-the-users-score-to-the-database">How to save the user's score to the database</h3>
<p>Before you can save a user's score to the database, you need to check if the user's data already exists – meaning the user has taken a test before. If true, you need to update the user's score with the latest test score. Otherwise, add the data to the database.</p>
<p>The code snippet below accepts the user's score and user's ID (from the session data) and saves the user's score to Supabase.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> saveScore = <span class="hljs-keyword">async</span> (userScore: <span class="hljs-built_in">number</span>, userID: <span class="hljs-built_in">string</span>) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">//👇🏻 check if the user data exists</span>
        <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase
            .from(<span class="hljs-string">"scores"</span>)
            .select()
            .eq(<span class="hljs-string">"user_id"</span>, userID);
        <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;

        <span class="hljs-comment">//👇🏻 if the user data does not exist, insert a new one</span>
        <span class="hljs-keyword">if</span> (error || !data.length) {
            <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase
                .from(<span class="hljs-string">"scores"</span>)
                .insert({
                    attempts: [{ score: userScore, date: getCurrentDate() }],
                    total_score: userScore,
                    user_id: userID,
                })
                .single();
            <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">//👇🏻 if the user data exists, update the attempts and total_score</span>
            <span class="hljs-keyword">const</span> { data: updateData, error } = <span class="hljs-keyword">await</span> supabase
                .from(<span class="hljs-string">"scores"</span>)
                .update({
                    attempts: [
                        ...data[<span class="hljs-number">0</span>].attempts,
                        { score: userScore, date: getCurrentDate() },
                    ],
                    total_score: data[<span class="hljs-number">0</span>].total_score + userScore,
                })
                .eq(<span class="hljs-string">"user_id"</span>, userID);
            <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
        }
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.log(err);
    }
};
</code></pre>
<h3 id="heading-how-to-retrieve-data-from-supabase">How to retrieve data from Supabase</h3>
<p>Recall that you need to rank the users based on their scores on the Leaderboard screen and retrieve the user's attempts on the Profile screen.</p>
<p>The code snippet below accepts a user's ID and retrieves the attempts and total score from the database.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getUserAttempts = <span class="hljs-keyword">async</span> (userID: <span class="hljs-built_in">string</span>) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase
            .from(<span class="hljs-string">"scores"</span>)
            .select(<span class="hljs-string">"attempts, total_score"</span>)
            .eq(<span class="hljs-string">"user_id"</span>, userID);
        <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
        <span class="hljs-keyword">return</span> { attempts: data[<span class="hljs-number">0</span>].attempts, total_score: data[<span class="hljs-number">0</span>].total_score };
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> { attempts: <span class="hljs-string">""</span>, total_score: <span class="hljs-number">0</span> };
    }
};
</code></pre>
<p>The code snippet below retrieves the top ten users from the database based on their score.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getLeaderBoard = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase
            .from(<span class="hljs-string">"scores"</span>)
            .select(<span class="hljs-string">"total_score, user_id"</span>)
            .order(<span class="hljs-string">"total_score"</span>, { ascending: <span class="hljs-literal">false</span> })
            .limit(<span class="hljs-number">10</span>);
        <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
        <span class="hljs-keyword">return</span> data;
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
};
</code></pre>
<p>Congratulations! You've successfully completed the project for this tutorial.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you’ve learned how to:</p>
<ul>
<li>build React Native mobile applications with Expo,</li>
<li>style your mobile applications with <a target="_blank" href="https://www.nativewind.dev/">Tailwind CSS</a>,</li>
<li>create stack and tab screen navigations using <a target="_blank" href="https://docs.expo.dev/router/introduction/">Expo Router</a>,</li>
<li>use Supabase and leverage its authentication and database features to build full-stack applications.</li>
</ul>
<p>Supabase is an amazing tool that enables you to build a full-stack software application with no hassle. If you are looking forward to shipping great software products or side projects faster, consider using Supabase.</p>
<p>Expo also saves us from the complexities of setting up and developing mobile applications using the <a target="_blank" href="https://reactnative.dev/docs/environment-setup">React Native CLI</a>. It enables you to focus more on building your applications while it handles the necessary configurations, including deployment.</p>
<p>Feel free to customise the application using <a target="_blank" href="https://chat.openai.com/">ChatGPT</a> to generate questions and answers tailored to any niche or topic.</p>
<p>The source code for this tutorial is available in this <a target="_blank" href="https://github.com/dha-stix/techtest-app">GitHub repository</a>.</p>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add Tailwind CSS to Your React Native Expo App ]]>
                </title>
                <description>
                    <![CDATA[ Tailwind CSS has been quite popular in the web development world due to its utility-first approach and seamless integration.  However, when developing mobile apps with React Native, integrating Tailwind CSS may be challenging. But guess what? Not any... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tailwindcss-in-react-native-expo/</link>
                <guid isPermaLink="false">66b9ee776a5986e4892f960b</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CSS3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tailwind ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ John Caleb ]]>
                </dc:creator>
                <pubDate>Tue, 27 Feb 2024 09:22:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/FREECODE-CAMP-DEFAULT-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Tailwind CSS has been quite popular in the web development world due to its utility-first approach and seamless integration. </p>
<p>However, when developing mobile apps with React Native, integrating Tailwind CSS may be challenging. But guess what? Not anymore. With the development of tools such as <a target="_blank" href="https://www.nativewind.dev/">NativeWind</a>, React Native developers can leverage Tailwind CSS power to design stunning and responsive mobile UIs easily.</p>
<p>In this tutorial, you'll learn the process of integrating Tailwind CSS to your React Native <a target="_blank" href="https://expo.io/">Expo</a> app using NativeWind. We'll also build a simple login screen with NativeWind.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ul>
<li><a class="post-section-overview" href="#heading-whats-nativewind">What's NativeWind?</a></li>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-getting-started">Getting Started</a> </li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-new-expo-app">How to Create A New Expo App</a></li>
<li><a class="post-section-overview" href="#heading-how-to-install-nativewind">How to Install NativeWind</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-tailwind-css">How to Set Up Tailwind CSS</a></li>
<li><a class="post-section-overview" href="#heading-how-to-configure-nativewind-with-babel">How to Configure NativeWind With Babel</a></li>
<li><a class="post-section-overview" href="#heading-how-to-style-with-nativewind">How to Style with NativeWind</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-a-simple-login-screen">How to Build A Simple Login Screen</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-whats-nativewind">What's NativeWind?</h2>
<p>NativeWind acts as a bridge between Tailwind CSS and React Native Expo, allowing developers to take advantage of Tailwind's utility-first approach in their mobile app development workflow. </p>
<p>NativeWind provides various benefits to developers, some of these benefits include:</p>
<ul>
<li><strong>Familiar Syntax</strong>: Developers that are familiar with Tailwind CSS can easily migrate to using NativeWind in their React Native projects, easing the learning curve.</li>
<li><strong>Consistent Styling:</strong> NativeWind ensures consistent styling across platforms by offering a single collection of components and services.</li>
<li><strong>Flexibility</strong>: NativeWind allows developers to easily adapt and extend styles to meet the app's design specifications.</li>
</ul>
<p>Overall, It provides a collection of components and tools that are very similar to Tailwind CSS, allowing developers to create shorter, more concise code while preserving flexibility and consistency across platforms.</p>
<blockquote>
<p>Tailwind makes writing code feel like I’m using a design tool - Didier Catz</p>
</blockquote>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Basic Understanding of React Native Expo and Tailwind CSS.</li>
<li>Node.js and npm (or yarn) installed.</li>
<li>Willingness to learn :)</li>
</ul>
<h2 id="heading-getting-started">Getting Started</h2>
<p>Before you dive into integrating Tailwind CSS into your React Native Expo app, you'll need to ensure that you have the necessary tools set up.</p>
<p>If you haven't already installed Expo and <a target="_blank" href="https://www.npmjs.com/package/expo-cli">expo-cli</a> globally, you can do so using npm or yarn:</p>
<pre><code class="lang-bash">npm install -g expo-cli
</code></pre>
<p>or </p>
<pre><code class="lang-bash">yarn global add expo-cli
</code></pre>
<h2 id="heading-how-to-create-a-new-expo-app">How to Create A New Expo App</h2>
<p>With expo-cli installed, you can now create a new React Native Expo project. </p>
<p>Navigate to the directory where you wish to create your project and open the terminal. You can do this by pressing <em>CTRL + `</em> on Visual Studio Code. Then execute this command in the terminal:</p>
<pre><code class="lang-bash">npx create-expo-app simpleproject
</code></pre>
<p>This command creates an expo project in your directory.</p>
<h2 id="heading-how-to-install-nativewind">How to Install NativeWind</h2>
<p>After creating your expo project, you can install NativeWind and its dependencies by running the following commands in your project's directory:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> simpleproject
npm i nativewind
npm i --dev tailwindcss@3.3.2
</code></pre>
<p>or</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> simpleproject
yarn add nativewind
yarn add --dev tailwindcss@3.3.2
</code></pre>
<p>Next, you'll need to create a <code>tailwind.config.js</code> file. To do this, run this command in your terminal:</p>
<pre><code class="lang-bash">npx tailwindcss init
</code></pre>
<p>This would result in a <code>tailwind.config.js</code> file in your project's root directory. </p>
<h2 id="heading-how-to-set-up-tailwind-css">How to Set Up Tailwind CSS</h2>
<p>To set up Tailwind CSS in your project, navigate to your <code>tailwind.config.js</code> file, and under <code>content</code>, enter the paths to your components. Your <code>tailwind.config.js</code> file would then look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./App.{js,jsx,ts,tsx}"</span>,
    <span class="hljs-string">"./&lt;custom directory&gt;/**/*.{js,jsx,ts,tsx}"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [],
};
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/code-1.png" alt="A screenshot of tailwind.conf.js file after adding path to components" width="600" height="400" loading="lazy">
<em>tailwind.conf.js file after adding paths to components</em></p>
<p>In the above example, you can replace <code>&lt;custom directory&gt;</code> with your directory's real name.</p>
<h2 id="heading-how-to-configure-nativewind-with-babel">How to Configure NativeWind with Babel</h2>
<p>You'll also need to configure NativeWind with Babel. To do this, include the NativeWind plugin in your project's <code>babel.conf.js</code> file:</p>
<pre><code class="lang-javascript">plugins: [<span class="hljs-string">"nativewind/babel"</span>],
</code></pre>
<p>The <code>babel.conf.js</code> file would look like this after adding the NativeWind plugin:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">api</span>) </span>{
  api.cache(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">presets</span>: [<span class="hljs-string">"babel-preset-expo"</span>],
    <span class="hljs-attr">plugins</span>: [<span class="hljs-string">"nativewind/babel"</span>],
  };
};
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/code2-2.png" alt="babel.conf.js file after adding nativewind plugin" width="600" height="400" loading="lazy">
<em>babel.conf.js file after adding nativewind plugin</em></p>
<p>By including the NativeWind plugin in the Babel configuration file you ensure that NativeWind's functionality is properly incorporated into your project's JavaScript codebase.</p>
<p> 🎉With this, NativeWind has been successfully integrated into your Expo app. The next step is to begin styling the app with NativeWind.</p>
<h2 id="heading-how-to-style-with-nativewind">How to Style with NativeWind</h2>
<p>To begin styling with NativeWind, go to your project's <code>App.js</code> file or the component you would like to style, which would look like this by default:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { StatusBar } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-status-bar"</span>;
<span class="hljs-keyword">import</span> { StyleSheet, Text, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</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">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Open up App.js to start working on your app!<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">StatusBar</span> <span class="hljs-attr">style</span>=<span class="hljs-string">'auto'</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#fff"</span>,
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">"center"</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">"center"</span>,
  },
});
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/appjs-default.png" alt="App.js boilerplate code" width="600" height="400" loading="lazy">
<em>App.js boilerplate code</em></p>
<p>Next, modify your component to get rid of any instances of <code>StyleSheet</code> abstraction. In this example, we'll modify the <code>App.js</code> code. After adjustments, we should have something like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { StatusBar } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-status-bar"</span>;
<span class="hljs-comment">// import { StyleSheet, Text, View } from "react-native";</span>
<span class="hljs-keyword">import</span> { Text, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</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">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">// &lt;View style={styles.container}&gt;</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'flex-1 justify-center items-center bg-white'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Open up App.js to start working on your app!<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">StatusBar</span> <span class="hljs-attr">style</span>=<span class="hljs-string">'auto'</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// const styles = StyleSheet.create({</span>
<span class="hljs-comment">//   container: {</span>
<span class="hljs-comment">//     flex: 1,</span>
<span class="hljs-comment">//     backgroundColor: "#fff",</span>
<span class="hljs-comment">//     alignItems: "center",</span>
<span class="hljs-comment">//     justifyContent: "center",</span>
<span class="hljs-comment">//   },</span>
<span class="hljs-comment">// });</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/newww.png" alt="App.js component after modification " width="600" height="400" loading="lazy">
<em>App.js component after modification</em></p>
<p>In the modified codeblock, we remove all occurrences of <code>StyleSheet</code> abstractions, including the import statement for <code>stylesheet</code> and the <code>StyleSheet.create</code> function, and we replace <code>style</code> with <code>className</code> in the <code>App.js</code> return function.</p>
<p>Having cleared that up, all you need to do is write Tailwind CSS classes into your app <code>className</code> to begin implementing Tailwind CSS in your application. You'll see this in a bit as we build a simple login screen with NativeWind.</p>
<h2 id="heading-how-to-build-a-simple-login-screen">How to Build A Simple Login Screen</h2>
<p>Now, let's dive into building a simple login screen using NativeWind. We'll continue with the initial setup in the <code>App.js</code> file and gradually add components to create the login UI.</p>
<p>First, let's replace the existing code in the <code>App.js</code> file with the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { StatusBar } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-status-bar"</span>;
<span class="hljs-keyword">import</span> { Text, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</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">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'flex-1 justify-center items-center bg-white'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">StatusBar</span> <span class="hljs-attr">style</span>=<span class="hljs-string">'auto'</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-center mt-3 text-2xl font-light text-orange-300'</span>&gt;</span>
        Login
      <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      {/* Additional components goes here */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
 );
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/firstt.png" alt="Starter code for login screen UI" width="600" height="400" loading="lazy">
<em>Starter code for login screen UI</em></p>
<p>The code above imports the essential components from React Native and Expo. We then use a <code>View</code> component to define the structure of our login screen, which is styled with NativeWind's utility classes. Inside the <code>View</code>, we have a <code>Text</code> component that displays "Login" with styling applied using NativeWind classes.</p>
<p>Next, you can add your login form components, such as username and password input fields, a login button, and any other necessary elements. Here is an example of how you can extend the login screen:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { StatusBar } <span class="hljs-keyword">from</span> <span class="hljs-string">"expo-status-bar"</span>;
<span class="hljs-keyword">import</span> { Text, View, TouchableOpacity, TextInput } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</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">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'flex-1 justify-center items-center bg-white'</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">StatusBar</span> <span class="hljs-attr">style</span>=<span class="hljs-string">'auto'</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-center mt-3 text-2xl font-light text-orange-300'</span>&gt;</span>
        Login
      <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      {/* Additional components goes here */}
      <span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-5 mx-5'</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">View</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-gray-400'</span>&gt;</span>EMAIL:<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">TextInput</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter Email...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'border border-dotted p-2 text-gray-500 border-amber-400 mt-1'</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-3'</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-gray-400'</span>&gt;</span>PASSWORD:<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">TextInput</span>
            <span class="hljs-attr">secureTextEntry</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter Password...'</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">'border text-gray-500 border-dotted p-2 border-amber-400 mt-1'</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">TouchableOpacity</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'bg-orange-300 p-3 mt-4'</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-center text-base text-white'</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">TouchableOpacity</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-center font-normal text-gray-500 text-base mt-3'</span>&gt;</span>
          OR
        <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-4'</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">TouchableOpacity</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'flex flex-row items-center justify-center p-2 bg-orange-300'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-white mx-2 text-sm'</span>&gt;</span>Sign In With Google<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">TouchableOpacity</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mt-6 flex-row justify-center'</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">''</span>&gt;</span>New to FreeCodeCamp? <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">TouchableOpacity</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'text-amber-500'</span>&gt;</span>Create an Account<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">TouchableOpacity</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
  );
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/nextend-1.png" alt="Extended login screen UI with additional components " width="600" height="400" loading="lazy">
<em>Extended login screen UI with additional components</em></p>
<p>In this expanded version, we've included <code>TextInput</code> components for the username and password input fields, as well as a <code>TouchableOpacity</code> for the login button. Styling is done with NativeWind's utility classes to provide a clean and consistent appearance.</p>
<p>Furthermore, once you've finished creating your login screen using NativeWind in your React Native Expo project, you'll want to test it to check if everything works properly. You can do this by running this command on your terminal:</p>
<pre><code class="lang-bash">expo start
</code></pre>
<p>This command will launch the bundler and generate a QR code. To open the app, scan the QR code displayed in the terminal with your emulator's camera, or press "a" for Android or "i" for iOS.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot_20240223-015329.png" alt="Output of the code in an emulator" width="600" height="400" loading="lazy">
<em>Output of the code in an emulator</em></p>
<p>If you need to, you can access <a target="_blank" href="https://github.com/thejohncaleb/simpleproject">the complete project code</a> on GitHub.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Integrating Tailwind CSS into a React Native Expo project with NativeWind has various benefits, including increased developer efficiency, code consistency, and performance. Developers can easily create amazing mobile applications by leveraging the power of Tailwind CSS's utility-first approach and React Native's native features.</p>
<p>NativeWind makes it easy to apply Tailwind CSS to your React Native Expo app. Using Tailwind CSS in your mobile app development workflow opens up new possibilities for UI design and customization.</p>
<p>Remember, if you have any questions or just want to say hi, feel free to reach me on <a target="_blank" href="https://twitter.com/thejohncaleb">X(Twitter)</a> or my <a target="_blank" href="https://thejohncaleb.netlify.app/contact">website</a>. :)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Unleash the Power of React Native to Build Mobile Apps ]]>
                </title>
                <description>
                    <![CDATA[ Are you ready to dive into the world of React Native and create stunning mobile applications that work seamlessly on both Android and iOS platforms? We've got you covered! We just published a full React Native course on the freeCodeCamp.org YouTube c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-native-full-course-android-ios-development/</link>
                <guid isPermaLink="false">66b2064ba5be9a107f4341a1</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 10 Apr 2023 15:37:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/reactnative.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you ready to dive into the world of React Native and create stunning mobile applications that work seamlessly on both Android and iOS platforms? We've got you covered!</p>
<p>We just published a full React Native course on the freeCodeCamp.org YouTube channel. </p>
<p>Emma Williams created this course. She is a software developer who specializes in React Native.</p>
<p>Our comprehensive React Native course is specifically designed to take you from the basics of app development to creating your very own weather app with a sleek user interface and real-time data integration. The course will walk you through core concepts such as components, state management, hooks, and styling, while providing hands-on experience and practical examples.</p>
<h3 id="heading-course-overview">Course Overview</h3>
<p><strong>Introduction</strong><br>Start your journey into React Native with a brief overview of the framework, its benefits, and why it's the go-to choice for cross-platform mobile development.</p>
<p><strong>What is React Native and Expo?</strong><br>Understand the purpose of React Native and learn how Expo simplifies the development process by offering a suite of tools and services.</p>
<p><strong>Setting Up Your Environment</strong><br>Get up and running with Expo, set up a custom app, and configure Android Studio to kickstart your development process.</p>
<p><strong>The Directory Structure, Linting, and Prettier</strong><br>Familiarize yourself with the typical directory structure of a React Native project, and learn how to set up linting and Prettier for a clean and consistent codebase.</p>
<p><strong>Debugging and Native Components</strong><br>Discover the art of debugging in React Native and explore the power of native components to achieve a truly native look and feel.</p>
<p><strong>Core Components and JSX</strong><br>Understand the significance of core components and learn how to use JSX to build dynamic UIs.</p>
<p><strong>Working with Components</strong><br>Dive deep into the world of components, their purpose, and how to create your very first component.</p>
<p><strong>Styling and Layout Props</strong><br>Grasp the essentials of styling in React Native and learn how to use layout props to create responsive designs.</p>
<p><strong>Building the Weather App</strong><br>Put your newfound skills to the test as you create the current weather screen, upcoming weather component, and city screen. Learn to work with lists, images, and props, all while refining your codebase.</p>
<p><strong>Navigation and State Management</strong><br>Delve into the realm of navigation and state management, implementing tabs and using hooks like useState and useEffect to manage your app's state.</p>
<p><strong>Fetching Data and Integrating APIs</strong><br>Learn how to fetch data from the OpenWeatherMap API, get the user's location, and create your own custom hook to pass data to your components.</p>
<p><strong>Updating Components and Installing Moment</strong><br>Update your components to use real-time data, and install Moment to display dates and times in a user-friendly format.</p>
<p><strong>Error Handling and Final Refactoring</strong><br>Create an error screen to handle unexpected issues, and polish your app with some last refactoring.</p>
<p><strong>Bonus Material</strong><br>Enhance your React Native knowledge with bonus content covering advanced topics and best practices.</p>
<p>By the end of this comprehensive React Native course, you'll have the skills and confidence to build your own cross-platform mobile applications with ease. Whether you're an aspiring app developer or a seasoned professional looking to expand your toolkit, this course offers the perfect balance of theory and hands-on practice to elevate your React Native expertise. </p>
<p>Watch the full course on <a target="_blank" href="https://www.youtube.com/watch?v=obH0Po_RdWk">the freeCodeCamp.org YouTube channel</a> (5-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/obH0Po_RdWk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Manage State in React and React Native with the PullState Library ]]>
                </title>
                <description>
                    <![CDATA[ React and React Native are popular JavaScript libraries that allow developers to create complex user interfaces and mobile applications with ease.  One of the key benefits of both these libraries is that they each have the ability to manage their own... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/state-management-in-react-and-react-native-with-pullstate/</link>
                <guid isPermaLink="false">66bb889e6b3bd8d6bf25ae36</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Grant Riordan ]]>
                </dc:creator>
                <pubDate>Mon, 03 Apr 2023 21:47:52 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/Background1--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>React and React Native are popular JavaScript libraries that allow developers to create complex user interfaces and mobile applications with ease. </p>
<p>One of the key benefits of both these libraries is that they each have the ability to manage their own state within components. But managing state, along with sharable data, can be tricky – especially as the applications become more complex.</p>
<p>In this article, we will explore global state management – and in particular, how to use the Pullstate library. You'll learn how you can easily implement it into your React and React Native projects.</p>
<p>Pre-Requisites:</p>
<ul>
<li>Basic knowledge of React / React Native applications</li>
<li>Basic knowledge of CSS and styling (not essential)</li>
</ul>
<p><strong>Note</strong>: in this article, I will be using TypeScript and React Native. But the implementation and concepts will be exactly the same for JavaScript users and React (without the strongly typed variables).</p>
<h2 id="heading-what-is-state">What is State?</h2>
<p>State refers to an object that stores data which can change over time. It's a way to manage and update data within a component or application without affecting other parts of the application.  </p>
<p>State in React is like a backpack you carry around with you, containing things you might need for your day. It's a way to store and manage data in your app that can change over time, like what you've picked up or dropped off along the way.</p>
<h3 id="heading-local-vs-global-state">Local vs global state</h3>
<p>Component state is local to a specific component. This means that it's only accessible and modifiable within that component. You use component state to manage data that's specific to a single component – for example like form validation messages, or the visibility of certain UI (User Interface) elements.</p>
<p>Global state, on the other hand, refers to data that can be accessed and modified from multiple components across the entire application. Global state would be something that is managed by a state management library. It's useful for managing shared data across multiple components, like authentication status, user preferences, or shopping cart contents.   </p>
<p>Global state and component state both have their own advantages and disadvantages, depending on the specific needs of the application. </p>
<p>Global state can simplify data management and improve performance, but can also increase complexity if not managed correctly. Component state is simpler to manage and understand, but can lead to duplicated data and inconsistent behavior across the application.</p>
<h2 id="heading-what-are-state-management-libraries">What are State Management Libraries?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/SCR-20230325-oif-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>logos of popular state libraries</em></p>
<p>State management libraries in React are tools that help developers manage and organize the state of their applications more easily. These libraries are designed to handle complex state management scenarios in large-scale applications so you don't have to. They also help you create a more central, organized state.   </p>
<p>When talking about state management and data sharing, the most commonly talked about solution is Redux. But Redux is often seen as overly-complicated because it adds an additional layer of complexity. </p>
<p>Redux is designed to manage application state in a predictable and consistent manner, but it requires developers to learn a new set of concepts, such as actions, reducers, and the store. </p>
<p>Some other popular state management libraries in React include Zustand, MobX, and Recoil. These libraries provide features like global state management, immutability, and optimized re-rendering to help make applications more performant and easier to maintain.  </p>
<p>Using a state management library can make it easier for developers to handle the state of their application, and simplify the process of passing data between components. It can take some time to learn how to use these libraries effectively, but they can be very powerful tools for building complex React applications.</p>
<h2 id="heading-what-is-pullstate">What is Pullstate?</h2>
<p>Pullstate is a much simpler and more lightweight state management library for React. It simplifies the whole process and makes it easier to build scalable applications. </p>
<p>Since React Native is built on React, you can use Pullstate to build not only web applications but mobile ones, too. It is is based on the concept of "pulling" data from the state, rather than pushing data into it.</p>
<h3 id="heading-how-to-use-pullstate">How to use Pullstate</h3>
<p>In order to use Pullstate and get up an running, you'll first need to know which package manager you're using (yarn or npm).  </p>
<p>Open your existing React / React Native project, and in the terminal enter the following commands depending on whether you use npm or yarn:</p>
<pre><code class="lang-terminal">npm install pullstate
//or
yarn add pullstate
</code></pre>
<p>If you haven't already got a React Native application you can create one using the React Native cli.  </p>
<p>First, you'll need to make sure you <a target="_blank" href="https://nodejs.org/en/download">have Node.js installed</a>.  </p>
<p>Open the terminal to the folder where you would like to create your React Native application:</p>
<pre><code class="lang-terminal">npm uninstall -g react-native-cli
npx react-native init myReactNativeApp --template react-native-template-typescript
</code></pre>
<h2 id="heading-how-to-set-up-the-store">How to Set Up the Store</h2>
<p>The below code and corresponding image shows how to initialize the Pullstate store code for copying and pasting below (this is how I'll include all the code in this tutorial – code for copying, along with how it should look in a snapshot).  </p>
<p>You can put the below code in its own file, for example <code>store.ts</code> , in your project root folder.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {Store} <span class="hljs-keyword">from</span> <span class="hljs-string">'pullstate'</span>;

<span class="hljs-keyword">interface</span> UIStore {
  user: {
    firstName: <span class="hljs-built_in">string</span>;
    lastName: <span class="hljs-built_in">string</span>;
    acceptedTnC: <span class="hljs-built_in">boolean</span>;
  };
  preferences: {
    isDarkMode: <span class="hljs-built_in">boolean</span>;
    pushNotifications: <span class="hljs-built_in">boolean</span>;
  };
}

<span class="hljs-keyword">const</span> initialStore: UIStore = {
  user: {
    firstName: <span class="hljs-string">''</span>,
    lastName: <span class="hljs-string">''</span>,
    acceptedTnC: <span class="hljs-literal">false</span>,
  },
  preferences: {
    isDarkMode: <span class="hljs-literal">false</span>,
    pushNotifications: <span class="hljs-literal">false</span>,
  },
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Store&lt;UIStore&gt;({
  user: {
    firstName: <span class="hljs-string">''</span>,
    lastName: <span class="hljs-string">''</span>,
    acceptedTnC: <span class="hljs-literal">false</span>,
  },
  preferences: {
    isDarkMode: <span class="hljs-literal">false</span>,
    pushNotifications: <span class="hljs-literal">false</span>,
  },
});
</code></pre>
<p>Here's the snapshot of what that should look like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/store-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>image showing code snapshot of store configuration</em></p>
<h3 id="heading-what-is-this-code-doing">What is this code doing?</h3>
<p>First, we created an interface for the Pullstate store. This holds all the information we will need to store in state across the app. We have things like the user's first name and last name (so we can use them across the application). </p>
<p>The store can also hold nested objects, for example our <em>preferences</em> object, making managing state cleaner.  </p>
<p>To keep things simple and allow cleaner code in the future, I've created an initial store state. This resets all the state properties to their default values.<br>We can then (when needed) return the state back to its initial state quick and easily. This could be very useful in situations like <strong>logOut</strong>, <strong>onError</strong>, and so on.</p>
<p>Then we initialize the store and make it an exportable object. This means that after the first time we import the object (ideally at the top level of our application) it is then accessible throughout our app.</p>
<h2 id="heading-how-to-retrieve-data-from-the-store">How to Retrieve Data from the Store</h2>
<p>Ok, so we have our store, but how we do access this data within our component?<br>To retrieve the data from the store, we can utilize either the <strong>getRawState</strong> or  <strong>useState</strong> functions.</p>
<p><code>getRawState()</code> returns the raw state at this moment in time. When called it gives the live state of the pull state store. If the state is updated, the value will not be updated</p>
<p>For example in the code below, the <strong>acceptedTerms</strong> variable would be whatever value it was at time of calling <code>store.getRawState()</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/getRawState-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>example of using getRawState() function</em></p>
<p><code>useState()</code> acts in the same way as the React <code>useState()</code> function works. When the Pullstate store is updated, the acceptedTerms value will be be updated too, thus causing a re-render of the component. </p>
<p>Think of useState in Pullstate as a listening function – it waits for a value to be updated and then provides you with that new updated value.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/usestate.png" alt="Image" width="600" height="400" loading="lazy">
<em>example of using the store.useState() function</em></p>
<h2 id="heading-real-life-example">Real Life Example:</h2>
<p>Let's take a look at a real life example, involving accepting a terms and conditions page. The code below will:</p>
<ul>
<li>Create a card component with some terms, and </li>
<li>Have two buttons, 'Back' and 'Next', which will run a function on clicking.</li>
</ul>
<pre><code class="lang-typescript"><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> { StyleSheet, Text, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> { Card } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native-paper"</span>;
<span class="hljs-keyword">import</span> { store } <span class="hljs-keyword">from</span> <span class="hljs-string">"./store"</span>;<span class="hljs-keyword">import</span> { BlueButton } <span class="hljs-keyword">from</span> <span class="hljs-string">"../atoms/button"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> PullStateCard: React.FC = <span class="hljs-function">() =&gt;</span> {  
    <span class="hljs-keyword">const</span> handleAgreeTerms = <span class="hljs-function">() =&gt;</span> {
        store.update(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {     
            state.user.acceptedTnC = <span class="hljs-literal">true</span>;    
        });  
    };  

    <span class="hljs-keyword">const</span> handleDisagreeTerms = <span class="hljs-function">() =&gt;</span> { 
        store.update(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {      
            state.user.acceptedTnC = <span class="hljs-literal">false</span>;    
        });  
    };  

    <span class="hljs-keyword">return</span> (    
        &lt;Card style={[styles.marginTop, styles.padding]}&gt;
            &lt;Text&gt;Our services are provided on an <span class="hljs-keyword">as</span>-is basis. 
            We <span class="hljs-keyword">do</span> not guarantee the availability, accuracy, or completeness <span class="hljs-keyword">of</span> our services. 
            You may use our services only <span class="hljs-keyword">for</span> lawful purposes and <span class="hljs-keyword">in</span> accordance <span class="hljs-keyword">with</span> these terms and conditions.
            &lt;/Text&gt;
            &lt;Text style={{ marginTop: <span class="hljs-number">16</span> }}&gt;
                By clicking <span class="hljs-string">'Next'</span> you are agreeing to the terms and conditions <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span> app
            &lt;/Text&gt;
            &lt;View style={styles.row}&gt;
                &lt;BlueButton 
                    styleOverride={styles.button}
                    onPress={handleDisagreeTerms}
                    title=<span class="hljs-string">"Back"</span>/&gt;        
                &lt;BlueButton
                    styleOverride={styles.button}
                    onPress={handleAgreeTerms}
                    title=<span class="hljs-string">"Next"</span>/&gt;
            &lt;/View&gt;
        &lt;/Card&gt;  

       )
}
</code></pre>
<p>My custom buttons:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {
  StyleProp,
  StyleSheet,
  Text,
  TouchableOpacity,
  ViewStyle,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">interface</span> BlueButtonProps {
  onPress: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>;
  title: <span class="hljs-built_in">string</span>;
  styleOverride?: StyleProp&lt;ViewStyle&gt;;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> BlueButton: React.FC&lt;BlueButtonProps&gt; = <span class="hljs-function">(<span class="hljs-params">{
  onPress,
  title,
  styleOverride,
}</span>) =&gt;</span> (
  &lt;TouchableOpacity onPress={onPress} style={[styles.button, styleOverride]}&gt;
    &lt;Text style={styles.buttonText}&gt;{title}&lt;/Text&gt;
  &lt;/TouchableOpacity&gt;
);

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  button: {
    backgroundColor: <span class="hljs-string">'#007AFF'</span>,
    borderRadius: <span class="hljs-number">10</span>,
    padding: <span class="hljs-number">10</span>,
    alignItems: <span class="hljs-string">'center'</span>,
    marginVertical: <span class="hljs-number">10</span>,
  },
  buttonText: {
    color: <span class="hljs-string">'white'</span>,
    fontSize: <span class="hljs-number">16</span>,
    fontWeight: <span class="hljs-string">'bold'</span>,
  },
});
</code></pre>
<p>The Card component code would look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/CARD-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-dissecting-the-handle-functions">Dissecting the handle functions</h3>
<p>The handle functions are called when the buttons are clicked. Depending on which you click, a particular action will be carried out. But the underlying intent is the same, in that they both modify the state of the pull state store we created earlier.</p>
<p>One will set the <code>user.acceptedTnC</code> to <strong>true</strong>, and the other to <strong>false</strong>. We've used the <code>.update()</code>function on the <code>store</code> object we created earlier, and passed it an anonymous function to update the properties.   </p>
<p>The method is not limited to update just the one property, and you can update multiple properties at once, for example:</p>
<pre><code class="lang-typescript">store.update(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {  
    state.user.acceptedTnC = <span class="hljs-literal">true</span>;  
    state.user.firstName = <span class="hljs-string">"John"</span>;  
    state.user.lastName = <span class="hljs-string">"Doe"</span>;  
    state.preferences.pushNotifications = <span class="hljs-literal">true</span>;
});
</code></pre>
<h2 id="heading-why-is-pullstate-and-global-state-management-so-useful">Why is Pullstate and Global State Management So Useful?</h2>
<p>The beauty of using state in this way means that the component doesn't handle the store, the application does. You can then share this across the whole app, and have other components listen to these changes.  </p>
<p>Let's take the example above one step further and have a separate component that will show a relevant message that's dependent on the state of the acceptedTnC property.</p>
<pre><code><span class="hljs-keyword">const</span> styles = StyleSheet.create({  
    <span class="hljs-attr">disagree</span>: {    
        <span class="hljs-attr">color</span>: <span class="hljs-string">"red"</span>,
        <span class="hljs-attr">textDecoration</span>: <span class="hljs-string">"italic"</span>,
    },
    <span class="hljs-attr">accepted</span>: {
        <span class="hljs-attr">color</span>: <span class="hljs-string">"#0d8009"</span>,
    },  
    <span class="hljs-attr">marginTop</span>: {
        <span class="hljs-attr">marginTop</span>: <span class="hljs-number">10</span>,
    },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AgreedToTerms: React.FC = <span class="hljs-function">() =&gt;</span> {  
    <span class="hljs-keyword">const</span> acceptedTerms = store.useState(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.user.acceptedTnC);
    <span class="hljs-keyword">return</span> (    
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.marginTop}</span>&gt;</span> 
            {acceptedTerms ? (
                <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.accepted}</span>&gt;</span>
                    You have successfully accepted the Terms and Conditions                  <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>) : (
                 <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.disagree}</span>&gt;</span>
                     Please accept the Terms and Conditions by pressing 'Next'        
                     <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>)
            }
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
    )
};
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/03/accepted.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you import these components and add your own styling to the App.tsx (App.js for JS) like so:</p>
<pre><code class="lang-typescript">&lt;PullStateCard /&gt;
&lt;AgreedToTerms /&gt;
</code></pre>
<p>Your whole App.tsx code will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/app_whole.png" alt="Image" width="600" height="400" loading="lazy"></p>
<pre><code class="lang-typescript"><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> {
  SafeAreaView,
  ScrollView,
  StatusBar,
  StyleSheet,
  View,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;

<span class="hljs-keyword">import</span> {AgreedToTerms, PullStateCard} <span class="hljs-keyword">from</span> <span class="hljs-string">'./src/pullstate/pullstate_example'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;SafeAreaView&gt;
      &lt;StatusBar barStyle={<span class="hljs-string">'light-content'</span>} /&gt;
      &lt;ScrollView contentInsetAdjustmentBehavior=<span class="hljs-string">"automatic"</span>&gt;
        &lt;View style={styles.container}&gt;
          &lt;PullStateCard /&gt;
          &lt;AgreedToTerms /&gt;
        &lt;/View&gt;
      &lt;/ScrollView&gt;
    &lt;/SafeAreaView&gt;
  );
};

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    height: <span class="hljs-string">'100%'</span>,
    paddingHorizontal: <span class="hljs-number">16</span>,
    paddingVertical: <span class="hljs-number">16</span>,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Once you have copied the code, you can add your own styling where necessary and run the app. </p>
<p>Click the <strong>Next</strong> button, and your text will turn green and inform you that you've accepted the the terms.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/SCR-20230329-tsq.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you then click the <strong>Back</strong> button, you will see the text is red informing you that you need to accept the terms:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/SCR-20230329-ts9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is all powered by the global Pullstate store. There is no internal state on the <strong>AgreedToTerms</strong> component. </p>
<h2 id="heading-decoupling-logic">Decoupling Logic</h2>
<p>Decoupling refers to the practice of separating different parts of your code so that they are not tightly dependent on / related to each other.</p>
<p>Think of it like building with LEGOs. When you build with LEGOs, each piece can connect to other pieces, but they can also be easily disconnected and reconnected with other pieces. This makes it easier to change and modify your LEGO build.</p>
<p>Similarly, in programming, when we decouple our code, we make it easier to change and modify without affecting other parts of our code. This is especially important in large applications with many different components or modules.</p>
<p>By moving the 'agreed to terms' acceptance state to Pullstate, it can be added and removed to any component that should need it. It's not tightly coupled with the AgreedToTerms component, and it becomes a re-usable piece of state that is globally updated. For example we could use it elsewhere in the app as an authorization mechanism, to show / hide UI elements, and much more.</p>
<h2 id="heading-round-up">Round up</h2>
<p>I hope you've found this article useful and enjoyed this brief introduction to Pullstate and global state management.</p>
<p>What we've covered:</p>
<ul>
<li>What state management libraries are</li>
<li>An introduction to Pullstate and how to integrate it into your application</li>
<li>The benefits of Pullstate and how it works</li>
</ul>
<p>For any more questions don't hesitate to reach out to me on <a target="_blank" href="http://twitter.com/gweaths">Twitter</a>.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a 3D Tilting Card Effect in React Native ]]>
                </title>
                <description>
                    <![CDATA[ Recently, I came across a tutorial about how to create a 3D tilting card effect (with mouse tracking functionality) on Kevin Powell's YouTube channel. https://youtu.be/Z-3tPXf9a7M   Kevin used HTML, CSS, and JavaScript to create the markup, style the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-3d-tilting-card-in-react-native/</link>
                <guid isPermaLink="false">66d4617e33b83c4378a51851</guid>
                
                    <category>
                        <![CDATA[ mobile app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kingsley Ubah ]]>
                </dc:creator>
                <pubDate>Wed, 22 Feb 2023 16:35:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--14--1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Recently, I came across a tutorial about how to create a 3D tilting card effect (with mouse tracking functionality) on Kevin Powell's <a target="_blank" href="https://www.youtube.com/@KevinPowell">YouTube channel</a>.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Z-3tPXf9a7M" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>Kevin used HTML, CSS, and JavaScript to create the markup, style the card, and implement the mouse tracking functionality, respectively.</p>
<p>In this tutorial, we'll take a look at how to replicate the same project in React Native. We'll write pure HTML markup and use the <a target="_blank" href="https://www.npmjs.com/package/react-native-render-html">react-native-render-html</a> library to render it all into 100% native views.</p>
<p>This how our tilted cards will look by the end of this tutorial:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--20-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Feeling excited? Let's begin!</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To follow this tutorial, you'll need to have a good understanding of HTML. Knowledge of JavaScript and React Native is helpful but not necessary.</p>
<p>To follow this tutorial locally, on your computer, you need to have the following installed:</p>
<ul>
<li><p><a target="_blank" href="https://nodejs.org/en/download/">Node.js v10 or above</a></p>
</li>
<li><p><a target="_blank" href="https://developer.apple.com/xcode/">Xcode</a> or <a target="_blank" href="https://developer.android.com/studio">Android Studio</a> (set up to run the emulator)</p>
</li>
<li><p>React Native CLI</p>
</li>
</ul>
<p>For step-by-step instructions on how to set up your React Native development environment, you can read the <a target="_blank" href="https://reactnative.dev/docs/environment-setup">official documentation</a>.</p>
<p>Alternatively, if you don't have the time or resources to set it up from scratch, use <a target="_blank" href="https://snack.expo.dev/">Expo Snack</a>. This is a browser-based environment that lets you create React Native projects without needing to install anything.</p>
<p>Skip the <strong>Project Setup</strong> section if you're following this tutorial from Expo Snack. Otherwise proceed.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Run this command to install the React Native CLI tool using npm:</p>
<pre><code class="lang-c">npm install -g react-native-cli
</code></pre>
<p>Initialize a new project:</p>
<pre><code class="lang-c">react-native init my-app
</code></pre>
<p>Start your emulator:</p>
<pre><code class="lang-c">cd my-app &amp;&amp; npx react-native run-ios <span class="hljs-comment">// Start the iOS simulator</span>

<span class="hljs-comment">// OR</span>

cd my-app &amp;&amp; npx react-native run-android <span class="hljs-comment">// Android the android emulator</span>
</code></pre>
<p>These commands should have the simulator show up on the screen like this:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_8DBD080458BC82C38C5265C10E1A2396B6E318C95FC96C295C6A241E0096B1AD_1675941462527_emulator.png" alt="Image" width="160" height="314" loading="lazy"></p>
<p>Afterward, cd into your application folder on the terminal and run the following command to install <a target="_blank" href="https://www.npmjs.com/package/react-native-render-html">React Native HTML Renderer</a>:</p>
<pre><code class="lang-c">npm i react-native-render-html
</code></pre>
<p>That's all for installations. Let's get started with the code.</p>
<h2 id="heading-how-to-set-up-the-app">How to Set Up the App</h2>
<p>In this section, we'll import the React, <code>useWindowDimensions</code>, and <code>RenderHtml</code>, which we'll use create the layout of our application.</p>
<p>Open the App.js file in your project and clear the file content. Then start by importing the following:</p>
<pre><code class="lang-c"><span class="hljs-keyword">import</span> * as React from <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useWindowDimensions } from <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> RenderHtml from <span class="hljs-string">'react-native-render-html'</span>;
</code></pre>
<p>The <code>useWindowDimentions</code> hook allow us to access the dimensions of the viewport, which is how we're going to make the content responsive across all screen sizes. We'll use <code>RenderHtml</code> to render pure HTML markup into native views in our React Native application.</p>
<p>If you're following this tutorial on Expo Snack, you'll be asked to add the <code>react-native-render-html</code> package by clicking on <strong>Add dependency</strong> link at the page bottom. Click it.</p>
<p>Next, include the following code beneath the imports:</p>
<pre><code class="lang-c"><span class="hljs-keyword">const</span> source = {
  html: `
&lt;pre class=<span class="hljs-string">"language-css"</span> tabindex=<span class="hljs-string">"0"</span>&gt;&lt;code class=<span class="hljs-string">"language-css"</span>&gt;&lt;span class=<span class="hljs-string">"token selector"</span>&gt;.awesome-layouts&lt;/span&gt; &lt;span class=<span class="hljs-string">"token punctuation"</span>&gt;{&lt;/span&gt;
  &lt;span class=<span class="hljs-string">"token property"</span>&gt;display:&lt;/span&gt;&lt;/span&gt; &lt;span&gt;grid;&lt;/span&gt;
&lt;span <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">token</span> <span class="hljs-title">punctuation</span>"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;`
};</span>
</code></pre>
<p>As a value of the <code>html</code> property, we pass the HTML markup for the code block. It's pre-formatted content, so don't format the code (or it'll break). Just copy the code as it is and paste in your file.</p>
<p>Next, create <code>App()</code> as a functional component and a base stylesheet for the application. Return <code>&lt;RenderHTML /&gt;</code> and pass in both the pre-formatted code and stylesheet to the <code>source</code> and <code>baseStyles</code>, respectively:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> function <span class="hljs-title">App</span><span class="hljs-params">()</span> </span>{  
  <span class="hljs-keyword">const</span> { height, width } = useWindowDimensions();

  <span class="hljs-keyword">const</span> base = {
    height: height,
    width: width,
    flex: <span class="hljs-number">1</span>,
    alignItems: <span class="hljs-string">'center'</span>,
    justifyContent: <span class="hljs-string">'center'</span>,
    backgroundColor: <span class="hljs-string">'hsl(224, 32%, 12%)'</span>, 
    color: <span class="hljs-string">'white'</span>
  }

  <span class="hljs-keyword">return</span> (  
      &lt;RenderHtml      
      contentWidth={width}
      source={source}      
      baseStyle={base}      
      /&gt;
  );
}
</code></pre>
<p>On line 2, we access the height and width of the viewing device from the <code>useWindowsDimensions()</code> call. We then set the height and width of the root element to that of the screen, align the content to the center, set the background color to dark-blue, and the text color to white.</p>
<p>Save the file. You should find a UI that looks like the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--15-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next up is styling the code block.</p>
<h2 id="heading-how-to-style-the-code">How to Style the <code>&lt;pre&gt;</code> Code</h2>
<p>In this section, we'll place the pre-formatted code inside a card, tilt the card, and apply different colors to the code to make it appear like real CSS code.</p>
<h3 id="heading-1-how-to-put-the-code-in-a-card">1. How to put the code in a card</h3>
<p>All of the stylesheets for our HTML markup will go inside the <code>htmlStyles</code> object. The first property of <code>htmlStyles</code> is the stylesheet for the <code>&lt;pre&gt;</code> element:</p>
<pre><code class="lang-c"><span class="hljs-keyword">const</span> htmlStyles = { 
  pre: {
    fontSize: <span class="hljs-string">'18px'</span>,
    fontWeight: <span class="hljs-string">'bold'</span>,
    backgroundColor: <span class="hljs-string">'hsl(222, 45%, 7%)'</span>,
    padding: <span class="hljs-string">'10px'</span>,
    borderRadius: <span class="hljs-string">'5px'</span>,    
    transform: [
      { perspective: <span class="hljs-number">5000</span> },
      { rotateX: <span class="hljs-string">'8deg'</span>},
      { rotateY: <span class="hljs-string">'20deg'</span>},
      { skewX: <span class="hljs-string">'8deg'</span>},
    ],
  },  
}
</code></pre>
<p>This adds a dark-blue background around the code, rounds the box edges, increases the font size and weight of the code, and adds some padding between the box and the code.</p>
<p>With <code>transform</code>, we rotate the card 8 degree around the x-axis and 20 degrees along the y-axis, tilting the card a little bit.</p>
<p>We also set perspective to 5000 to set a significant distance between the user and the card (which makes it more realistic).</p>
<p>To see this in effect, you need to add the <code>tagsStyles</code> property to <code>&lt;RenderHTML /&gt;</code> and pass <code>htmlStyles</code> as its value, like so:</p>
<pre><code class="lang-c">&lt;RenderHtml      
  contentWidth={width}
  source={source}      
  baseStyle={base}
  tagsStyles={htmlStyles}      
/&gt;
</code></pre>
<p>Save the file and go over to your device/emulator to see the effect:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--16-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, we style the text by adding different colors to it.</p>
<h3 id="heading-2-how-to-style-the-code">2. How to style the code</h3>
<p>We don't want all of the code to be white. Instead, we want the <code>.selector</code> to be pink, the <code>.property</code> greenish-blue and the rest white. We'll add some extra CSS to get these colors.</p>
<p>Recall that each <code>&lt;span&gt;</code> element within <code>&lt;pre&gt;</code> had a class name of either <code>.selector</code>, <code>.property</code> or <code>.punctuation</code>. With react-native-render-html, we can't use the class selector to target elements, so this will not work:</p>
<pre><code class="lang-c">.selector {
    color: <span class="hljs-string">'hsl(338, 70%, 65%)'</span>
}
</code></pre>
<p>We'll have to define the CSS code directly on the respective HTML tags with the inline <code>style</code> property. So for the <code>&lt;span&gt;</code> element with the class name <code>selector</code>, apply the pink color like so:</p>
<pre><code class="lang-c">style=<span class="hljs-string">"color: hsl(338, 70%, 65%);</span>
</code></pre>
<p>As for the <code>&lt;span&gt;</code> element with class name of <code>property</code>, apply a greenish-blue color to it:</p>
<pre><code class="lang-c">style=<span class="hljs-string">"color: hsl(183, 70%, 62%);</span>
</code></pre>
<p>Next, we'll add some glow to the text. To do this, we'll use the React Native versions of the <code>text-shadow</code> property and we'll apply it to the <code>&lt;span&gt;</code> elements (add inside the <code>htmlStyles</code> object):</p>
<pre><code class="lang-c"> span: {
    textShadowColor: <span class="hljs-string">'currentColor'</span>,
    textShadowOffset: {width: <span class="hljs-number">-0.5</span>, height: <span class="hljs-number">0.5</span>},
    textShadowRadius: <span class="hljs-number">4</span>
  },
</code></pre>
<p>By setting <code>textShadowColor</code> to <code>currentColor</code>, we're telling React Native to use the same color of each text as shadow color, so the selector will have a pink glow and the property will have a greenish-blue glow.</p>
<p>Here's the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--17-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now we're done with styling the code. In the next section, we'll turn the card into a 3D element.</p>
<h2 id="heading-how-to-make-the-card-3d-and-add-different-layers">How to Make the Card 3D and Add Different Layers</h2>
<p>In this section, we'll add a second layer to the card and transform the card into a 3D object. The second box will be an image gradient containing the colors blue and red.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/angryimg.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the <code>source</code> object, underneath the <code>&lt;pre /&gt;</code> tag, create an <code>&lt;img&gt;</code> element and point its <code>src</code> to the image above (upload the image to a place like Dropbox and get the URL):</p>
<pre><code class="lang-c">&lt;img src=<span class="hljs-string">"put-the-url-to-your-image-here"</span>/&gt;
</code></pre>
<p>Next, add the following stylesheet to the <code>htmlStyles</code> object:</p>
<pre><code class="lang-c">  img: {    
    top: <span class="hljs-number">-95</span>,
    right: <span class="hljs-number">7</span>, 
    zIndex: <span class="hljs-number">-10</span>,   
    height: <span class="hljs-number">95</span>,
    width: <span class="hljs-number">216</span>,    
    borderRadius: <span class="hljs-string">'5px'</span>, 
    overflow: <span class="hljs-string">'hidden'</span>,   
   transform: [
      { perspective: <span class="hljs-number">5000</span> },
      { rotateX: <span class="hljs-string">'8deg'</span>},
      { rotateY: <span class="hljs-string">'20deg'</span>},
      { skewX: <span class="hljs-string">'8deg'</span>},
    ],
  }
</code></pre>
<p>The above stylesheet basically overlaps the image with the code block (top and right), places the image behind the code block (z-index), makes the image the same size as the code block (height and width) and the same shape as well (transform).</p>
<p>Here's the final look of our application:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--18-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To straighten the button, you simply reset the value of <code>rotateX</code> and <code>rotateY</code> to 0 for both the <code>&lt;img&gt;</code> and the <code>&lt;pre&gt;</code> element:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/Untitled-design--19-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Grab the full source code from <a target="_blank" href="https://snack.expo.dev/@ubahthebuilder/69e153">here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, we took a tilted 3D card made with HTML and CSS and replicated it in React Native.</p>
<p>To achieve this, we used react-native-html-renderer to render HTML to React Native elements, and React Native specific properties to style the elements.</p>
<p>I hope you enjoyed following this tutorial as I did making it. You can give feedback on this article or discuss opportunities with me on <a target="_blank" href="https://twitter.com/kingchuuks">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Native Tutorial – How to Create a Simple Responsive Layout for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Having a responsive layout is an important component of user interface (UI) design. It enables a website or application to automatically adjust its size and layout based on the size of the user's device and screen. This provides an optimal viewing ex... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/responsive-layout-react-native/</link>
                <guid isPermaLink="false">66d4619837bd2215d1e24608</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ responsive design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kingsley Ubah ]]>
                </dc:creator>
                <pubDate>Thu, 02 Feb 2023 23:50:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/02/pexels-luna-lovegood-4087468.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Having a responsive layout is an important component of user interface (UI) design. It enables a website or application to automatically adjust its size and layout based on the size of the user's device and screen. This provides an optimal viewing experience.</p>
<p>Responsive layouts also give the user a more consistent and unified look across all devices and platforms, while still making sure the user's experience is tailored to their device.</p>
<p>This helps create a more user-friendly experience and improves the overall usability of the website or application.</p>
<p>In this tutorial, I'll show you how to create a simple responsive layout in React Native. You can preview the demo <a target="_blank" href="https://snack.expo.dev/@ubahthebuilder/67d71a">here</a>.</p>
<h2 id="heading-requirements">Requirements</h2>
<p>To follow this tutorial, you'll need:</p>
<ul>
<li><p>A basic understanding of React Native</p>
</li>
<li><p><a target="_blank" href="https://snack.expo.dev/">Expo Snack</a> – a browser-based development environment for React Native</p>
</li>
</ul>
<h2 id="heading-how-to-create-a-responsive-layout">How to Create a Responsive Layout</h2>
<p>Go to Expo Snack and clear the content of App.js. Start by importing the React library and Text, View, and Stylesheet UI components:</p>
<pre><code class="lang-c"><span class="hljs-keyword">import</span> * as React from <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Text, View, StyleSheet } from <span class="hljs-string">'react-native'</span>;
</code></pre>
<p>React Native is based on React, so we need to import the React library explicitly. The Text component is used to create text, View is a container element used for grouping other elements, and StyleSheet is used to define the components stylesheet.</p>
<p>Next, define an App function and return two custom components, <code>&lt;Header /&gt;</code> and <code>&lt;Footer /&gt;</code>:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> function <span class="hljs-title">App</span><span class="hljs-params">()</span> </span>{
  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.container}&gt;
      &lt;Header /&gt;
      &lt;Boxes /&gt;
    &lt;/View&gt;
  );
}
</code></pre>
<p>Here we wrap <code>&lt;Header /&gt;</code> and <code>&lt;Footer /&gt;</code> inside a <code>&lt;View /&gt;</code> container. Both of them are custom components, and because they haven't been created yet, you'll get a ReferenceError. Ignore that for now.</p>
<p>Next, create the stylesheet for this component and define the styling for the container element:</p>
<pre><code class="lang-c"><span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    flex: <span class="hljs-number">1</span>,   
  },  
});
</code></pre>
<p>This <code>flex:1</code> value tells the component to fill all available space and to share the space evenly amongst its children.</p>
<p>Let's now create both the <code>&lt;Header&gt;</code> and <code>&lt;Boxes/&gt;</code> components.</p>
<h2 id="heading-how-to-create-the-component">How to Create the <code>&lt;Header /&gt;</code> Component</h2>
<p>In the components folder, create a new file named Header.js. Then import both the following:</p>
<pre><code class="lang-c"><span class="hljs-keyword">import</span> * as React from <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Text, View, StyleSheet} from <span class="hljs-string">'react-native'</span>;
</code></pre>
<p>Create a <code>&lt;Header /&gt;</code> function and return a single <code>&lt;View /&gt;</code> with text saying "Header Component":</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> function <span class="hljs-title">Header</span><span class="hljs-params">()</span> </span>{
  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.header}&gt;
      &lt;Text&gt;Header Component&lt;/Text&gt;
    &lt;/View&gt;
  );
}
</code></pre>
<p>The <code>&lt;View /&gt;</code> is linked to a <code>style</code> property of <code>header</code>. Keep in mind that we want to make this header responsive on all screen sizes. Let's do that using CSS.</p>
<pre><code class="lang-c"><span class="hljs-keyword">const</span> styles = StyleSheet.create({
  header: {
    width: <span class="hljs-string">"100%"</span>,
    height: <span class="hljs-string">"15%"</span>,
    alignItems: <span class="hljs-string">'center'</span>,
    justifyContent: <span class="hljs-string">'center'</span>,
    backgroundColor: <span class="hljs-string">'grey'</span>    
  },
});
</code></pre>
<p>With this stylesheet, we're specifying that, no matter how big or small the screen, the header should span the whole width of the screen (100%) and take only 15% of the screen's height.</p>
<p>Now to the boxes.</p>
<h2 id="heading-how-to-create-the-component-1">How to Create the <code>&lt;Boxes /&gt;</code> Component</h2>
<p>Below the header we want to place two boxes, one to the left and one to the right. We also want the boxes to take up a certain width and height based on the screen dimension of the target device.</p>
<p>Inside the components folder, create a new file named boxes.js. Start by importing the following:</p>
<pre><code class="lang-c"><span class="hljs-keyword">import</span> * as React from <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Text, View, StyleSheet} from <span class="hljs-string">'react-native'</span>;
</code></pre>
<p>Next, create a Boxes function and return the markup for the boxes:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> function <span class="hljs-title">Boxes</span><span class="hljs-params">()</span> </span>{
  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.container}&gt;
      &lt;View style={styles.box}&gt;
        &lt;View style={styles.inner}&gt;
          &lt;Text&gt;Box <span class="hljs-number">1</span>&lt;/Text&gt;
        &lt;/View&gt;                      
      &lt;/View&gt;
      &lt;View style={styles.box}&gt;
        &lt;View style={styles.inner}&gt;
          &lt;Text&gt;Box <span class="hljs-number">2</span>&lt;/Text&gt;
        &lt;/View&gt;                      
      &lt;/View&gt;
    &lt;/View&gt;
  );
}
</code></pre>
<p>Here we have two boxes placed inside the container. Inside both is a View element containing the text label for each box.</p>
<p>Next, define the styling for the component. We'll create three sets of styles, one for the box container, one for the inner wrapper and the last for the boxes themselves.</p>
<pre><code class="lang-c"><span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    width: <span class="hljs-string">"100%"</span>,
    height: <span class="hljs-string">"85%"</span>,
    alignItems: <span class="hljs-string">"center"</span>,
    flexDirection: <span class="hljs-string">'row'</span>,
    flexWrap: <span class="hljs-string">'wrap'</span>    
  },
  box: {
    width: <span class="hljs-string">"50%"</span>,
    height: <span class="hljs-string">"50%"</span>,
    padding: <span class="hljs-number">5</span>
  },
  inner: {
    flex: <span class="hljs-number">1</span>,
    backgroundColor: <span class="hljs-string">"#D3D3D3"</span>,
    alignItems: <span class="hljs-string">'center'</span>,
    justifyContent: <span class="hljs-string">'center'</span>
  }
});
</code></pre>
<p>Recall that the header takes up 15% of the screen's height. Therefore, with the above CSS, we specify that the box container should take up the remaining 85%.</p>
<p>We align the boxes to the center and place them in a row arrangement. Each box takes up 50% of the total height and width, and we apply padding of 5 to space them a bit.</p>
<p>Now that we have both the responsive Header and Boxes ready, let's import them to App.js and see the results.</p>
<h2 id="heading-how-to-import-and">How to Import <code>&lt;Header /&gt;</code> and <code>&lt;Boxes /&gt;</code></h2>
<p>Inside App.js, at the top of the file, import both <code>&lt;Header /&gt;</code> and <code>&lt;Boxes /&gt;</code> like so:</p>
<pre><code class="lang-c"><span class="hljs-keyword">import</span> Header from <span class="hljs-string">"./components/Header"</span>
<span class="hljs-keyword">import</span> Boxes from <span class="hljs-string">"./components/Boxes"</span>
</code></pre>
<p>Once the app compiles, you should see your responsive layout on the right side of your window looking like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/UI.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Final look of responsive layout</em></p>
<p>This arrangement will be consistent across all screen sizes because we used percentages to set the height and width instead of fixed width values.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this tutorial helped you understand React Native positioning better. You should now be able to create responsive layouts in your React Native app using the techniques we covered in this post.</p>
<p>Grab my FREE freelance writing checklist <a target="_blank" href="https://kingchuks.gumroad.com/l/fwc">here</a>. Have a great week!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Calculator App Using React Native – A Step-by-Step Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ By Muhammad Adam A calculator application is a simple application that is always available on every Android, iOS, and desktop device.  In this article, we will build a calculator application using React Native and Expo. So why are we using these tool... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-calculator-app-using-react-native-a-step-by-step-tutorial/</link>
                <guid isPermaLink="false">66d45dd5787a2a3b05af4398</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 02 Feb 2023 19:29:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/banner---how-to-build-calculator-app-using-react-native-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Muhammad Adam</p>
<p>A calculator application is a simple application that is always available on every Android, iOS, and desktop device. </p>
<p>In this article, we will build a calculator application using React Native and Expo. So why are we using these tools? </p>
<p>React Native is a JavaScript-based framework you can use to develop mobile applications on two operating systems at the same time – Android and iOS. React Native was first launched in 2015 by Facebook, and is open source.</p>
<p>You can find out more information about React Native <a target="_blank" href="https://reactnative.dev/docs/getting-started">here</a>.</p>
<p>Expo is a set of tools, libraries, and services that you can use to simplify your React Native code. So you can run React Native apps on the Expo emulator.</p>
<p>You can find out more information about Expo <a target="_blank" href="https://expo.dev/">here</a>.</p>
<p>Before we start making a calculator application, you'll first need to install Node.js, React Native, and Expo on your computer.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ol>
<li>Install Node.js – you can see how to install it <a target="_blank" href="https://nodejs.org/en/download/">here</a>.</li>
<li>Install React Native – you can see the installation documentation <a target="_blank" href="https://reactnative.dev/docs/environment-setup">here</a>.</li>
<li>Install Expo – you can see the installation documentation <a target="_blank" href="https://reactnative.dev/docs/environment-setup">here</a>.</li>
</ol>
<h2 id="heading-step-1-create-a-new-project">Step 1: Create a New Project</h2>
<p>The first step is to create a new project. Use the Expo CLI to create the React Native code base with the following command:</p>
<pre><code class="lang-bash">$ expo init calculator-app
</code></pre>
<p>Then you'll have the choice of starting the project you want. Here we choose the blank option and use JavaScript as below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-349.png" alt="Image" width="600" height="400" loading="lazy">
<em>choose template expo project</em></p>
<p>After that, the process will continue by downloading all the dependencies.</p>
<h2 id="heading-step-2-create-the-button-component">Step 2: Create the Button Component</h2>
<p>When you're developing applications using React Native, make sure you break down UI components into smaller components so that the code you create can be reusable.</p>
<p>First, create a new folder called “<strong>components</strong>” to store your component code. The first component we will create is a Button, so create a new file called <strong>Button.js</strong>. Here is the source code for the Button component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Dimensions, StyleSheet, Text, TouchableOpacity } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ onPress, text, size, theme }) =&gt; {
  <span class="hljs-keyword">const</span> buttonStyles = [styles.button];
  <span class="hljs-keyword">const</span> textStyles = [styles.text];

  <span class="hljs-keyword">if</span> (size === <span class="hljs-string">"double"</span>) {
    buttonStyles.push(styles.buttonDouble);
  }

  <span class="hljs-keyword">if</span> (theme === <span class="hljs-string">"secondary"</span>) {
    buttonStyles.push(styles.buttonSecondary);
    textStyles.push(styles.textSecondary);
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (theme === <span class="hljs-string">"accent"</span>) {
    buttonStyles.push(styles.buttonAccent);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TouchableOpacity</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{onPress}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{buttonStyles}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{textStyles}</span>&gt;</span>{text}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">TouchableOpacity</span>&gt;</span></span>
  );
};
</code></pre>
<p>Code explanation:</p>
<ul>
<li>In line 3, there are four props that we need in order to make this Button component: onPress, text, size and theme.</li>
<li>Each of the props has a function like onPress for handling actions on buttons.</li>
<li>The button component that we created has 2 types of themes, secondary and accent, and 1 size, double.</li>
<li>The button component uses the default React Native component, TouchableOpacity.</li>
</ul>
<p>After we make the code from the component, don’t forget to add the styling for this button component. Here is the code for the component's styling:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// set dimmenstion</span>
<span class="hljs-keyword">const</span> screen = Dimensions.get(<span class="hljs-string">"window"</span>);
<span class="hljs-keyword">const</span> buttonWidth = screen.width / <span class="hljs-number">4</span>;

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">button</span>: {
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#333333"</span>,
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">height</span>: <span class="hljs-built_in">Math</span>.floor(buttonWidth - <span class="hljs-number">10</span>),
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">"center"</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">"center"</span>,
    <span class="hljs-attr">borderRadius</span>: <span class="hljs-built_in">Math</span>.floor(buttonWidth),
    <span class="hljs-attr">margin</span>: <span class="hljs-number">5</span>,
  },
  <span class="hljs-attr">text</span>: {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"#fff"</span>,
    <span class="hljs-attr">fontSize</span>: <span class="hljs-number">24</span>,
  },
  <span class="hljs-attr">textSecondary</span>: {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"#060606"</span>,
  },
  <span class="hljs-attr">buttonDouble</span>: {
    <span class="hljs-attr">width</span>: screen.width / <span class="hljs-number">2</span> - <span class="hljs-number">10</span>,
    <span class="hljs-attr">flex</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">"flex-start"</span>,
    <span class="hljs-attr">paddingLeft</span>: <span class="hljs-number">40</span>,
  },
  <span class="hljs-attr">buttonSecondary</span>: {
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#a6a6a6"</span>,
  },
  <span class="hljs-attr">buttonAccent</span>: {
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#ffc107"</span>,
  },
});
</code></pre>
<p>So the complete code of our button component is as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Dimensions, StyleSheet, Text, TouchableOpacity } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ onPress, text, size, theme }) =&gt; {
  <span class="hljs-keyword">const</span> buttonStyles = [styles.button];
  <span class="hljs-keyword">const</span> textStyles = [styles.text];

  <span class="hljs-keyword">if</span> (size === <span class="hljs-string">"double"</span>) {
    buttonStyles.push(styles.buttonDouble);
  }

  <span class="hljs-keyword">if</span> (theme === <span class="hljs-string">"secondary"</span>) {
    buttonStyles.push(styles.buttonSecondary);
    textStyles.push(styles.textSecondary);
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (theme === <span class="hljs-string">"accent"</span>) {
    buttonStyles.push(styles.buttonAccent);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TouchableOpacity</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{onPress}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{buttonStyles}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{textStyles}</span>&gt;</span>{text}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">TouchableOpacity</span>&gt;</span></span>
  );
};

<span class="hljs-comment">// set dimmenstion</span>
<span class="hljs-keyword">const</span> screen = Dimensions.get(<span class="hljs-string">"window"</span>);
<span class="hljs-keyword">const</span> buttonWidth = screen.width / <span class="hljs-number">4</span>;

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">button</span>: {
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#333333"</span>,
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">height</span>: <span class="hljs-built_in">Math</span>.floor(buttonWidth - <span class="hljs-number">10</span>),
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">"center"</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">"center"</span>,
    <span class="hljs-attr">borderRadius</span>: <span class="hljs-built_in">Math</span>.floor(buttonWidth),
    <span class="hljs-attr">margin</span>: <span class="hljs-number">5</span>,
  },
  <span class="hljs-attr">text</span>: {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"#fff"</span>,
    <span class="hljs-attr">fontSize</span>: <span class="hljs-number">24</span>,
  },
  <span class="hljs-attr">textSecondary</span>: {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"#060606"</span>,
  },
  <span class="hljs-attr">buttonDouble</span>: {
    <span class="hljs-attr">width</span>: screen.width / <span class="hljs-number">2</span> - <span class="hljs-number">10</span>,
    <span class="hljs-attr">flex</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">alignItems</span>: <span class="hljs-string">"flex-start"</span>,
    <span class="hljs-attr">paddingLeft</span>: <span class="hljs-number">40</span>,
  },
  <span class="hljs-attr">buttonSecondary</span>: {
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#a6a6a6"</span>,
  },
  <span class="hljs-attr">buttonAccent</span>: {
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#ffc107"</span>,
  },
});
</code></pre>
<h2 id="heading-step-3-create-the-row-component">Step 3: Create the Row Component</h2>
<p>The next component that we will create is a Row component. This component is useful for creating rows when we want to process layouts. </p>
<p>Here is the code for the Row component and its styling code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { StyleSheet, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;

<span class="hljs-keyword">const</span> Row = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>;
};

<span class="hljs-comment">// create styles of Row</span>
<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flexDirection</span>: <span class="hljs-string">"row"</span>,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Row;
</code></pre>
<p>Here's what's going on:</p>
<ul>
<li>In the row component, there is 1 prop that we need: children.</li>
<li>The row component uses the default View component from React Native.</li>
<li>flexDirection: “row” in this styling is used to make the layout a row.</li>
</ul>
<h2 id="heading-step-4-create-the-calculator-logic">Step 4: Create the Calculator Logic</h2>
<p>Create a new folder called util and a new file <strong>calculator.js</strong>. Here we will create function logic in the calculator application which we will implement later in the <strong>App.js</strong> file. Here is the complete code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">currentValue</span>: <span class="hljs-string">"0"</span>,
  <span class="hljs-attr">operator</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">previousValue</span>: <span class="hljs-literal">null</span>,
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handleNumber = <span class="hljs-function">(<span class="hljs-params">value, state</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (state.currentValue === <span class="hljs-string">"0"</span>) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${value}</span>`</span> };
  }

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${state.currentValue}</span><span class="hljs-subst">${value}</span>`</span>,
  };
};

<span class="hljs-keyword">const</span> handleEqual = <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { currentValue, previousValue, operator } = state;

  <span class="hljs-keyword">const</span> current = <span class="hljs-built_in">parseFloat</span>(currentValue);
  <span class="hljs-keyword">const</span> previous = <span class="hljs-built_in">parseFloat</span>(previousValue);
  <span class="hljs-keyword">const</span> resetState = { <span class="hljs-attr">operator</span>: <span class="hljs-literal">null</span>, <span class="hljs-attr">previousValue</span>: <span class="hljs-literal">null</span> };

  <span class="hljs-keyword">switch</span> (operator) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"+"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${previous + current}</span>`</span>,
        ...resetState,
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"-"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${previous - current}</span>`</span>,
        ...resetState,
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"*"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${previous * current}</span>`</span>,
        ...resetState,
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"/"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${previous / current}</span>`</span>,
        ...resetState,
      };

    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-comment">// calculator function</span>
<span class="hljs-keyword">const</span> calculator = <span class="hljs-function">(<span class="hljs-params">type, value, state</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"number"</span>:
      <span class="hljs-keyword">return</span> handleNumber(value, state);
    <span class="hljs-keyword">case</span> <span class="hljs-string">"clear"</span>:
      <span class="hljs-keyword">return</span> initialState;
    <span class="hljs-keyword">case</span> <span class="hljs-string">"posneg"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">parseFloat</span>(state.currentValue) * <span class="hljs-number">-1</span>}</span>`</span>,
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"percentage"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">parseFloat</span>(state.currentValue) * <span class="hljs-number">0.01</span>}</span>`</span>,
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"operator"</span>:
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">operator</span>: value,
        <span class="hljs-attr">previousValue</span>: state.currentValue,
        <span class="hljs-attr">currentValue</span>: <span class="hljs-string">"0"</span>,
      };
    <span class="hljs-keyword">case</span> <span class="hljs-string">"equal"</span>:
      <span class="hljs-keyword">return</span> handleEqual(state);
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> state;
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> calculator;
</code></pre>
<p>And here's what's going on:</p>
<ul>
<li>initialState is used to give the default value to our calculator app.</li>
<li>The function handleNumber serves to return the value of the calculator, and has 2 props – value and state.</li>
<li>The function handle Equal serves to process the set value of each mathematical operator and returns its value.</li>
<li>The function calculator validates every given operator. For example, if the number calls the handleNumber function, if it is clear it will return the default state value from initiaState, and so on.</li>
</ul>
<h2 id="heading-step-5-refactor-the-appjs-file">Step 5: Refactor the App.js File</h2>
<p>After we have created all the components and the logic process, the next step is to make adjustments to the code in the App.js file. Here is the full code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { SafeAreaView, StyleSheet, Text, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Button"</span>;
<span class="hljs-keyword">import</span> Row <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Row"</span>;
<span class="hljs-keyword">import</span> calculator, { initialState } <span class="hljs-keyword">from</span> <span class="hljs-string">"./util/calculator"</span>;

<span class="hljs-comment">// create class component of App</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  state = initialState;

  <span class="hljs-comment">// handle tap method</span>
  HandleTap = <span class="hljs-function">(<span class="hljs-params">type, value</span>) =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> calculator(type, value, state));
  };

  <span class="hljs-comment">// render method</span>
  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
        {/* Status bae here */}
        <span class="hljs-tag">&lt;<span class="hljs-name">SafeAreaView</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.value}</span>&gt;</span>
            {parseFloat(this.state.currentValue).toLocaleString()}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>

          {/* Do create componentRow */}
          <span class="hljs-tag">&lt;<span class="hljs-name">Row</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"C"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"secondary"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("clear")}
            /&gt;

            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"+/-"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"secondary"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("posneg")}
            /&gt;

            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"%"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"secondary"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("percentage")}
            /&gt;

            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"/"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"accent"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("operator", "/")}
            /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">Row</span>&gt;</span>

          {/* Number */}
          <span class="hljs-tag">&lt;<span class="hljs-name">Row</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"7"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 7)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"8"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 8)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"9"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 9)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"X"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"accent"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("operator", "*")}
            /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">Row</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">Row</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"5"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 5)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"6"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 6)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"7"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 7)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"-"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"accent"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("operator", "-")}
            /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">Row</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">Row</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 1)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 2)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"3"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 3)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"+"</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"accent"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("operator", "+")}
            /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">Row</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">Row</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", 0)} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"."</span> <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("number", ".")} /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
              <span class="hljs-attr">text</span>=<span class="hljs-string">"="</span>
              <span class="hljs-attr">theme</span>=<span class="hljs-string">"primary"</span>
              <span class="hljs-attr">onPress</span>=<span class="hljs-string">{()</span> =&gt;</span> this.HandleTap("equal", "=")}
            /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">Row</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">SafeAreaView</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
    );
  }
}

<span class="hljs-comment">// create styles of app</span>
<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  <span class="hljs-attr">container</span>: {
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">"#202020"</span>,
    <span class="hljs-attr">justifyContent</span>: <span class="hljs-string">"flex-end"</span>,
  },
  <span class="hljs-attr">value</span>: {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"#fff"</span>,
    <span class="hljs-attr">fontSize</span>: <span class="hljs-number">42</span>,
    <span class="hljs-attr">textAlign</span>: <span class="hljs-string">"right"</span>,
    <span class="hljs-attr">marginRight</span>: <span class="hljs-number">20</span>,
    <span class="hljs-attr">marginBottom</span>: <span class="hljs-number">10</span>,
  },
});
</code></pre>
<p>A few quick notes:</p>
<ul>
<li>handleTap is a function that we created which aims to provide state values and call utils/calculator.</li>
<li>Here we call two components, Button and Row, to design the appearance of the calculator such as its numbers, mathematical operations, and the calculation process.</li>
</ul>
<h2 id="heading-step-6-run-the-app">Step 6: Run the App</h2>
<p>In this step we will try to run the calculator application on the device or we can use an emulator. Here I use the iPhone simulator from MacOS. Run the command below to run the program:</p>
<pre><code class="lang-bash">$ yarn ios
</code></pre>
<p>The running process here uses Expo as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-350.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If the compiling process is complete, then the display of the calculator application that we programmed will be like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image-351.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>That’s enough for this article. You learned about styling, components, props, and states in React Native and built a functional calculator app.</p>
<p>If you need the full source code, you can visit my GitHub repository here: <a target="_blank" href="https://github.com/bangadam/calculator-app">https://github.com/bangadam/calculator-app</a></p>
<h3 id="heading-thanks-for-reading">Thanks For Reading!</h3>
<p>Available for a new project! Let’s have a talk.<br>Email: <a target="_blank" href="mailto:bangadam.dev@gmail.com">bangadam.dev@gmail.com</a><br>Linkedin: <a target="_blank" href="https://www.linkedin.com/in/bangadam/">https://www.linkedin.com/in/bangadam</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React.js vs React Native – What's the Difference? ]]>
                </title>
                <description>
                    <![CDATA[ Are React.js and React Native the same? If you're new to the world of web and mobile development, you might be wondering the same thing. As a newbie, it's easy to assume that React.js are React Native are the same. After all, they both have "React" a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-js-vs-react-native-whats-the-difference/</link>
                <guid isPermaLink="false">66d46192a326133d12440a9e</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kingsley Ubah ]]>
                </dc:creator>
                <pubDate>Wed, 01 Feb 2023 00:41:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/02/pexels-pixabay-209339.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are React.js and React Native the same?</p>
<p>If you're new to the world of web and mobile development, you might be wondering the same thing.</p>
<p>As a newbie, it's easy to assume that React.js are React Native are the same. After all, they both have "React" as part of their name.</p>
<p>Though React.js and React Native share a lot in common, they're different from each other. In this article, I'll explain both React.js and React Native, then I'll list out their similarities and differences. By the end of this article, you'll have a clear knowledge of both tools and what kind of app they're used to build.</p>
<p>In order to have a clear understanding of the difference between React.js and React Native, we have to first dive into how a website is rendered on a web browser.</p>
<h2 id="heading-how-websites-get-rendered-html-css-and-javascript">How Websites Get Rendered: HTML, CSS, and JavaScript</h2>
<p>When you type the URL of a website into your browser's address bar and click enter, the browser requests the website, and the web server sends an HTML file to the browser.</p>
<p>The HTML file contains the content of the webpage and the linked files such as images, videos, and stylesheets. The web browser parses the HTML file and builds a Document Object Model (DOM) which is a tree-like structure containing the elements of the page (for example, buttons, paragraphs, links, and so on).</p>
<p>The browser initiates requests for the linked files and downloads them to the computer. It then parses the linked files, such as CSS and JavaScript, and applies the styling to the content, making it more presentable to the user. After all the files are downloaded, the browser renders the content on the screen.</p>
<p>The browser also runs any JavaScript code to make the page interactive. So, for example, if the user fills the wrong information in a form, JavaScript can be used to insert a <code>&lt;div&gt;</code> element into the page showing an error message to the user.</p>
<p>However, one of the biggest problems of inserting elements into the DOM with JavaScript is that the code is not reusable. For example, if you want to insert the same button into the page, but with different background colors, you have to create the element twice in JavaScript:</p>
<pre><code class="lang-c">let blueBtn = document.createElement(<span class="hljs-string">"button"</span>).style.backgroundColor(<span class="hljs-string">"blue"</span>)
let redBtn = document.createElement(<span class="hljs-string">"button"</span>).style.backgroundColor(<span class="hljs-string">"red"</span>)

<span class="hljs-comment">// Insert blue and red button into the page</span>
</code></pre>
<p>This is just a simple example. With complex user interfaces, you can imagine how long and confusing things can become. React was developed to solve this problem by making the process of creating web apps much more organized and intuitive.</p>
<h2 id="heading-what-is-reactjs">What is React.js?</h2>
<p>Technically speaking, ReactJS is an open-source, front-end JavaScript library for building user interfaces or UI components. In simple terms, this means that you can use React to build all the parts of a website that the user can see and interact with on their browser window.</p>
<p>So what's the difference between using plain JavaScript and React? Well, React makes the process of designing the user interface much easier. It allows you to create elements that you can easily re-use in other parts of the website or app.</p>
<p>With JavaScript, I previously mentioned how you'll need to write the same code twice to create the same button with different colors, which could lead to complexity in large projects.</p>
<p>React's component architecture solves this problem brilliantly. With React, you define a single piece of the UI, say a button, as a component.</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">const</span> <span class="hljs-title">Button</span> <span class="hljs-params">(props)</span> </span>=&gt; {
    <span class="hljs-keyword">return</span> (
        &lt;div&gt;
            &lt;button style={props.color}&gt;Submit&lt;/button&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>The component in this case is a function that returns HTML-like syntax called JSX, which defines the presentation and look of the component on the web browser.</p>
<p>Now, say you want to use the same button (but with different colors) in multiple places on your website. Instead of creating each button from scratch with different color properties (as you would with JavaScript), with React, you simple use the same <code>&lt;Button&gt;</code> element and pass a different color to each of them as <code>props</code>, creating variations of the same button.</p>
<pre><code class="lang-c">&lt;Button color=<span class="hljs-string">"red"</span> /&gt;
&lt;Button color=<span class="hljs-string">"blue"</span> /&gt;
&lt;Button color=<span class="hljs-string">"green"</span> /&gt;
</code></pre>
<p>This method keeps everything simple and organized, which is the whole essence of the React.js library.</p>
<p>Another benefit of using React for UI development is separation of concerns. This means that the data used in a component exists separately from the logic, which exists separately from the view layer.</p>
<p>Here's an example:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">const</span> <span class="hljs-title">Button</span> <span class="hljs-params">(props)</span> </span>=&gt; {
    <span class="hljs-comment">// component data</span>
    <span class="hljs-keyword">const</span> [btnText, setBtnText] = useState(<span class="hljs-string">"Submit"</span>)

    <span class="hljs-comment">// component logic</span>
    function onClick() {
        setBtnText(<span class="hljs-string">"Submitted!"</span>)
    }

    <span class="hljs-keyword">return</span> (
        <span class="hljs-comment">// component view</span>
        &lt;div&gt;
            &lt;button style={props.color}&gt;{btnText}&lt;/button&gt;
        &lt;/div&gt;
    )
}
</code></pre>
<p>As you can see here, the state, logic and presentation of a component are all separate from each other, making React UI components easier to understand and compose.</p>
<p>To conclude, React is a JavaScript library designed to simplify the process to building the frontend of web applications.</p>
<h2 id="heading-what-is-react-native">What is React Native?</h2>
<p>Here's the main difference between ReactJS and React Native:</p>
<ul>
<li><p>React JS is used to build the user interface of web applications (that is, apps that run on a web browser)</p>
</li>
<li><p>React Native is used to build applications that run on both iOS and Android devices (that is, cross-platform mobile applications)</p>
</li>
<li><p>React uses HTML, CSS and JavaScript to create interactive user interfaces. React Native, on the other hand, uses native UI components and APIs to create mobile apps.</p>
</li>
</ul>
<p>Both React JS and React Native share the same syntax. React Native was created as a way for developers to build cross-platform mobile applications using their existing knowledge of web development tools like HTML, CSS, JavaScript and the React core library.</p>
<p>In fact, some of the libraries commonly used together with React to develop web applications also have a mobile version for building apps in React Native – for example, Axios, Bootstrap CSS, and Tailwind CSS.</p>
<p>Here are the things React DOM and React Native have in common:</p>
<ol>
<li><p>They both use the same core React library.</p>
</li>
<li><p>They both use the same component-based architecture, which means that developers can break down their applications into smaller, more manageable pieces.</p>
</li>
<li><p>They both use JavaScript as their programming language, and JSX as their templating language.</p>
</li>
<li><p>Both React DOM and React Native use virtual DOMs to render their applications.</p>
</li>
<li><p>Both React DOM and React Native also use the same styling techniques and components, through React Native's is a bit different.</p>
</li>
<li><p>They both utilize Chrome DevTools for debugging applications.</p>
</li>
<li><p>They use the same JavaScript APIs.</p>
</li>
<li><p>Both were developed in Meta. React was developed by a software engineer named Jordan Walke while React Native was born from a hackathon.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article explored the differences between React DOM and React Native, two popular JavaScript tools. React DOM is primarily used for web development, while React Native is used for mobile development.</p>
<p>React DOM uses HTML, CSS, and JavaScript for layout and styling, and allows developers to create interactive user interfaces. React Native, on the other hand, uses native UI components and APIs to create cross-platform mobile applications.</p>
<p>Thanks for reading. Grab my FREE freelance writing checklist <a target="_blank" href="https://kingchuks.gumroad.com/l/fwc">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
