<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rushikesh Pandit</title>
    <description>The latest articles on Forem by Rushikesh Pandit (@rushikeshpandit).</description>
    <link>https://forem.com/rushikeshpandit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1365257%2F16e12541-8d0a-40b4-8fde-24b2c6c5ec69.jpeg</url>
      <title>Forem: Rushikesh Pandit</title>
      <link>https://forem.com/rushikeshpandit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rushikeshpandit"/>
    <language>en</language>
    <item>
      <title>Handling Sensitive UI Data in React Native: Practical Approaches Across iOS and Android</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Tue, 31 Mar 2026 10:06:41 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/handling-sensitive-ui-data-in-react-native-practical-approaches-across-ios-and-android-41nk</link>
      <guid>https://forem.com/rushikeshpandit/handling-sensitive-ui-data-in-react-native-practical-approaches-across-ios-and-android-41nk</guid>
      <description>&lt;h1&gt;
  
  
  Handling Sensitive UI Data in React Native
&lt;/h1&gt;

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

&lt;p&gt;As mobile applications increasingly deal with sensitive user data—financial details, personal health information, authentication flows—UI-level privacy becomes a non-trivial concern.&lt;/p&gt;

&lt;p&gt;While backend security is well understood, protecting &lt;strong&gt;what’s visible on the screen&lt;/strong&gt; is often overlooked.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Problem
&lt;/h2&gt;

&lt;p&gt;Each platform handles screen privacy differently:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Uses &lt;code&gt;FLAG_SECURE&lt;/code&gt; to block screenshots and recordings
&lt;/li&gt;
&lt;li&gt;Requires &lt;code&gt;ContentObserver&lt;/code&gt; to detect screenshots
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;No direct API to block screenshots
&lt;/li&gt;
&lt;li&gt;Relies on &lt;code&gt;UITextField&lt;/code&gt; (&lt;code&gt;isSecureTextEntry&lt;/code&gt;) behavior
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Areas to Address
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Screen Capture Protection
&lt;/h3&gt;

&lt;p&gt;Android provides native support. iOS requires workaround techniques.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. App Switcher Snapshots
&lt;/h3&gt;

&lt;p&gt;Apps must hide sensitive data before going to background.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Screenshot Detection
&lt;/h3&gt;

&lt;p&gt;Detection is possible, prevention is limited.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Clipboard Management
&lt;/h3&gt;

&lt;p&gt;Sensitive data should be cleared proactively.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Copy/Paste Restrictions
&lt;/h3&gt;

&lt;p&gt;Needs native-level interception.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architectural Approach
&lt;/h2&gt;

&lt;p&gt;A scalable approach includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hooks for declarative usage
&lt;/li&gt;
&lt;li&gt;Imperative APIs for lifecycle control
&lt;/li&gt;
&lt;li&gt;View wrappers for sensitive UI
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;iOS limitations on screenshot blocking
&lt;/li&gt;
&lt;li&gt;Android emulator bypasses
&lt;/li&gt;
&lt;li&gt;UX vs security balance
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;UI privacy is a cross-platform engineering problem requiring thoughtful abstraction and careful handling of OS differences.&lt;/p&gt;

&lt;p&gt;If you're building anything in fintech, banking, or enterprise on React Native and want a lightweight security layer without pulling in a large SDK — give it a try.&lt;br&gt;
Feedback welcome, especially if you hit false positives on specific devices.&lt;/p&gt;

&lt;p&gt;Built with Swift, Kotlin, and C++. No external dependencies.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-native-privacy-guard-kit" rel="noopener noreferrer"&gt;npm Package&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-privacy-guard-kit" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-privacy-guard-kit/blob/master/README.md" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-privacy-guard-kit/issues" rel="noopener noreferrer"&gt;Issue Tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found this helpful? Drop a ❤️ on the article and ⭐ on GitHub!&lt;br&gt;
Questions or suggestions? Drop them in the comments below! &lt;/p&gt;

&lt;p&gt;Feel free to reach out to me if you have any questions or need assistance.&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering #DevCommunity #root-detection #jailbreak-detection #mobile-security&lt;br&gt;
 #device-integrity&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>security</category>
    </item>
    <item>
      <title>Detecting Rooted &amp; Jailbroken Devices in React Native — How I Built It and What I Learned</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Sun, 08 Mar 2026 06:08:32 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/detecting-rooted-jailbroken-devices-in-react-native-how-i-built-it-and-what-i-learned-1jaa</link>
      <guid>https://forem.com/rushikeshpandit/detecting-rooted-jailbroken-devices-in-react-native-how-i-built-it-and-what-i-learned-1jaa</guid>
      <description>&lt;p&gt;I've been working on a React Native security library for the past few months. Not because there wasn't anything out there, but because most existing solutions were either outdated, not maintained, or didn't support the New Architecture.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;react-native-root-jail-detect&lt;/strong&gt; from scratch — native Swift for iOS, Kotlin + C++ for Android, full TurboModules and Fabric support.&lt;br&gt;
Here's what I learned building it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem With Simple File Checks
&lt;/h2&gt;

&lt;p&gt;Most jailbreak detection libraries do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;jailbreakPaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"/Applications/Cydia.app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jailbreakPaths&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contains&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;FileManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fileExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;atPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works — until it doesn't. &lt;code&gt;/bin/sh&lt;/code&gt; exists on stock iOS. &lt;code&gt;/var/log/syslog&lt;/code&gt; exists on non-jailbroken devices. And on the simulator, the entire macOS filesystem is exposed, so paths like &lt;code&gt;/usr/bin/ssh&lt;/code&gt; and &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; all exist on a perfectly clean machine.&lt;/p&gt;

&lt;p&gt;The fix isn't just a better list of paths. It's knowing which paths are safe to check, where, and when.&lt;br&gt;
For the simulator I gate real-device-only checks behind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if targetEnvironment(simulator)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="cp"&gt;#else&lt;/span&gt;
&lt;span class="c1"&gt;// actual checks&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And paths like &lt;code&gt;/bin/bash&lt;/code&gt; only go into a &lt;code&gt;realDeviceOnlyPaths&lt;/code&gt; list that never runs on simulator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugger Detection Is Trickier Than It Looks
&lt;/h2&gt;

&lt;p&gt;There are four common approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;sysctl P_TRACED — most reliable
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;kinfo_proc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;MemoryLayout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;kinfo_proc&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;CTL_KERN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;KERN_PROC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;KERN_PROC_PID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;getpid&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sysctl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kp_proc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p_flag&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="kt"&gt;P_TRACED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Mach exception ports — catches LLDB specifically
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If EXC_MASK_BREAKPOINT has a valid port registered,&lt;/span&gt;
&lt;span class="c1"&gt;// something is listening for breakpoints&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;task_get_exception_ports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;mach_task_self_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;exception_mask_t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;EXC_MASK_BREAKPOINT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;masks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;behaviors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flavors&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Validate ports are not MACH_PORT_NULL — avoids false positives&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;ptrace TRACEME
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PT_TRACE_ME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;errno&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;EPERM&lt;/span&gt;  &lt;span class="c1"&gt;// already being traced&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;ptrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PT_DETACH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;TracerPid on Android
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/proc/self/status"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEachLine&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TracerPid:"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substringAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toInt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gotcha I hit: when you run your app via Xcode on a real device, Xcode automatically attaches LLDB. No breakpoints needed — just running from Xcode is enough to trigger all three iOS checks. The fix is gating these behind &lt;code&gt;#if DEBUG&lt;/code&gt; or a custom build flag like &lt;code&gt;SECURITY_CHECKS_ENABLED&lt;/code&gt; that you only set on Release and Staging schemes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frida Detection
&lt;/h2&gt;

&lt;p&gt;Frida is the main tool attackers use to hook into running apps and bypass security checks. Detecting it has a few layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Loaded image scan:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;_dyld_image_count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;_dyld_get_image_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowercased&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"frida"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gum-js"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Symbol lookup:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;suspiciousSymbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"gum_js_loop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"frida_agent_main"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"gum_script_backend_create"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;suspiciousSymbols&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UnsafeMutableRawPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;bitPattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  On Android — memory map scan:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ifstream&lt;/span&gt; &lt;span class="nf"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/proc/self/maps"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;getline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"frida"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;npos&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gum-js"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;npos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These only catch unobfuscated Frida. A determined attacker can rename the agent. But most script-kiddie level attacks use default Frida, and this catches those reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Runtime Watchdog
&lt;/h2&gt;

&lt;p&gt;This was the most interesting part to build. File path checks and debugger checks at launch are good, but they miss a common attack pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;App launches — device looks clean&lt;/li&gt;
&lt;li&gt;Attacker attaches Frida or LLDB after launch&lt;/li&gt;
&lt;li&gt;App never re-checks — attacker is in&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The watchdog solves this by running checks continuously on a background thread with randomized timing (±40% jitter to make it harder to predict and bypass):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;randomDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TimeInterval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;TimeInterval&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;jitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;TimeInterval&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;jitter&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;jitter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also checks for timing gaps — if the loop stalls for more than &lt;code&gt;interval * 4&lt;/code&gt;, it's a signal that the process was paused (e.g. by a debugger hitting a breakpoint):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lastRun&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleThreat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;detector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;detector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three response modes depending on how aggressive you want to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="kt"&gt;ProtectionMode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;logOnly&lt;/span&gt;       &lt;span class="c1"&gt;// log and continue&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;throwException&lt;/span&gt; &lt;span class="c1"&gt;// crash with reason&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;terminate&lt;/span&gt;     &lt;span class="c1"&gt;// kill(getpid(), SIGKILL)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For most apps I'd recommend &lt;code&gt;logOnly&lt;/code&gt; in staging and &lt;code&gt;terminate&lt;/code&gt; in production.&lt;/p&gt;

&lt;p&gt;Method Swizzling Detection — What Didn't Work&lt;br&gt;
My first approach was checking if &lt;code&gt;UIViewController.viewDidLoad&lt;/code&gt;'s IMP pointed back to UIKit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ This doesn't work&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;imagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowercased&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;imagePath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"uikit"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem: &lt;code&gt;viewDidLoad&lt;/code&gt; is a Swift method. Its IMP can point to a Swift-to-ObjC thunk or a dispatch stub — neither resolves to a UIKit path via &lt;code&gt;dladdr&lt;/code&gt;. Every app that overrides viewDidLoad would trigger this.&lt;br&gt;
The fix is checking pure ObjC methods with stable, well-known IMPs instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ This works&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;checks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="kt"&gt;AnyClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;#selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"libobjc"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;NSSelectorFromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"respondsToSelector:"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"libobjc"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSArray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="k"&gt;#selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;getter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSArray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"corefounda"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;// Verify each IMP resolves back to its expected binary via dladdr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-native-root-jail-detect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RootJailDetect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SecurityWatchdog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ProtectionMode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-root-jail-detect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// One-shot check
const isCompromised = await RootJailDetect.isDeviceRooted();
const reasons = await RootJailDetect.getDetectionReasons();

// Continuous monitoring
SecurityWatchdog.start({
  intervalMs: 3000,
  mode: ProtectionMode.TERMINATE,
});

// Stop monitoring
SecurityWatchdog.stop();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's Next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Certificate pinning integration&lt;/li&gt;
&lt;li&gt;Integrity check for the JS bundle itself&lt;/li&gt;
&lt;li&gt;Anti-tampering for the native binary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building anything in fintech, banking, or enterprise on React Native and want a lightweight security layer without pulling in a large SDK — give it a try.&lt;br&gt;
Feedback welcome, especially if you hit false positives on specific devices.&lt;/p&gt;

&lt;p&gt;Built with Swift, Kotlin, and C++. No external dependencies.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-native-root-jail-detect" rel="noopener noreferrer"&gt;npm Package&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-root-jail-detect" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-root-jail-detect/blob/master/README.md" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-root-jail-detect/issues" rel="noopener noreferrer"&gt;Issue Tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found this helpful? Drop a ❤️ on the article and ⭐ on GitHub!&lt;br&gt;
Questions or suggestions? Drop them in the comments below! &lt;/p&gt;

&lt;p&gt;Feel free to reach out to me if you have any questions or need assistance.&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering #DevCommunity #root-detection #jailbreak-detection #mobile-security&lt;br&gt;
 #device-integrity&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>security</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Published a Lightweight Library for Root/Jailbreak Detection React Native</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Sun, 22 Feb 2026 12:55:02 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/published-a-lightweight-library-for-rootjailbreak-detection-react-native-1eam</link>
      <guid>https://forem.com/rushikeshpandit/published-a-lightweight-library-for-rootjailbreak-detection-react-native-1eam</guid>
      <description>&lt;h2&gt;
  
  
  react-native-root-jail-detect
&lt;/h2&gt;

&lt;p&gt;Security is first thing in mobile app development, especially for banking, fintech, and enterprise applications. One critical security measure is detecting whether a device has been rooted (Android) or jailbroken (iOS). These compromised devices can expose your app to security vulnerabilities, data breaches, and unauthorized access.&lt;/p&gt;

&lt;p&gt;Today, I'm excited to share &lt;strong&gt;react-native-root-jail-detect&lt;/strong&gt; - a lightweight, open-source library that makes device security checks incredibly simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Another Root/Jailbreak Detection Library?
&lt;/h2&gt;

&lt;p&gt;When building security-focused React Native apps, I noticed most existing solutions were either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too heavy (bloating app size)&lt;/li&gt;
&lt;li&gt;Performance-intensive&lt;/li&gt;
&lt;li&gt;Closed-source or poorly maintained&lt;/li&gt;
&lt;li&gt;Complex APIs requiring extensive setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something different: simple, fast, tiny, and open source forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes This Special?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Incredibly Lightweight (~60KB)
&lt;/h3&gt;

&lt;p&gt;In a world where every kilobyte matters for app store optimization and user experience, this library weighs in at just ~60KB. That's smaller than most image assets in your app!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Installation is a breeze&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;react-native-root-jail-detect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clean &amp;amp; Simple API
&lt;/h3&gt;

&lt;p&gt;Forget complex configurations. One method, one promise, one boolean result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RootJailDetect&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-root-jail-detect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isCompromised&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;RootJailDetect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDeviceRooted&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isCompromised&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle accordingly - restrict features, show warning, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No configuration files, no initialization, no complex setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  New Architecture Ready
&lt;/h3&gt;

&lt;p&gt;Built from the ground up to support React Native's new architecture (Fabric and TurboModules). Future-proof your security implementation today.&lt;/p&gt;

&lt;h3&gt;
  
  
  Battle-Tested Detection Methods
&lt;/h3&gt;

&lt;p&gt;The library doesn't rely on a single detection method. Instead, it employs multiple techniques:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Android (Root Detection)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Binary file scanning (su, Superuser.apk, etc.)&lt;/li&gt;
&lt;li&gt;Runtime command execution attempts&lt;/li&gt;
&lt;li&gt;Multiple common root path checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For iOS (Jailbreak Detection)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cydia and jailbreak app detection&lt;/li&gt;
&lt;li&gt;Restricted file system access attempts&lt;/li&gt;
&lt;li&gt;Sandbox integrity verification&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Usage Example
&lt;/h2&gt;

&lt;p&gt;Here's how you might integrate it into a banking app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';
import { Alert } from 'react-native';
import RootJailDetect from 'react-native-root-jail-detect';

const BankingApp = () =&amp;gt; {
  const [securityPassed, setSecurityPassed] = useState(false);

  useEffect(() =&amp;gt; {
    performSecurityCheck();
  }, []);

  const performSecurityCheck = async () =&amp;gt; {
    try {
      const isRooted = await RootJailDetect.isDeviceRooted();

      if (isRooted) {
        Alert.alert(
          'Security Alert',
          'Your device appears to be rooted/jailbroken. ' +
          'For your security, some features will be restricted.',
          [
            { text: 'Learn More', onPress: () =&amp;gt; openSecurityInfo() },
            { text: 'OK', style: 'cancel' }
          ]
        );
        setSecurityPassed(false);
      } else {
        setSecurityPassed(true);
      }
    } catch (error) {
      console.error('Security check failed:', error);
      // Handle gracefully - perhaps allow access but log the incident
      setSecurityPassed(true);
    }
  };

  if (!securityPassed) {
    return &amp;lt;RestrictedModeUI /&amp;gt;;
  }

  return &amp;lt;FullBankingFeatures /&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Perfect Use Cases
&lt;/h2&gt;

&lt;p&gt;This library shines in applications requiring enhanced security:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Banking &amp;amp; Fintech Apps: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protect transaction integrity&lt;/li&gt;
&lt;li&gt;Comply with financial regulations&lt;/li&gt;
&lt;li&gt;Prevent unauthorized access to accounts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enterprise Applications &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforce corporate security policies&lt;/li&gt;
&lt;li&gt;MDM compliance&lt;/li&gt;
&lt;li&gt;Protect confidential business data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Healthcare Apps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HIPAA compliance requirements&lt;/li&gt;
&lt;li&gt;Patient data protection&lt;/li&gt;
&lt;li&gt;Secure telehealth platforms&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gaming Apps &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevent cheating&lt;/li&gt;
&lt;li&gt;Protect in-app purchases&lt;/li&gt;
&lt;li&gt;Maintain fair gameplay&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;E-commerce &amp;amp; Payment Apps &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PCI-DSS compliance&lt;/li&gt;
&lt;li&gt;Secure payment processing&lt;/li&gt;
&lt;li&gt;Fraud prevention&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Important Considerations
&lt;/h2&gt;

&lt;p&gt;While this library is highly effective, it's important to understand its limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not 100% Foolproof: Sophisticated concealment tools exist (RootCloak, Liberty, etc.)&lt;/li&gt;
&lt;li&gt;Part of Defense-in-Depth: Use alongside SSL pinning, code obfuscation, and server-side validation&lt;/li&gt;
&lt;li&gt;User Experience Matters: Don't alienate legitimate users with heavy-handed restrictions&lt;/li&gt;
&lt;li&gt;Keep Updated: Root/jailbreak methods evolve; regular updates are crucial&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices for Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Graceful Degradation
&lt;/h3&gt;

&lt;p&gt;Don't immediately lock users out. Consider a tiered approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleRootedDevice = async () =&amp;gt; {
  const isRooted = await RootJailDetect.isDeviceRooted();

  if (isRooted) {
    // Tier 1: Show warning, allow basic features
    showSecurityWarning();

    // Tier 2: Disable sensitive features
    disableBiometricAuth();
    disableStoredPaymentMethods();

    // Tier 3: Require additional verification
    requireTwoFactorAuth();

    // Analytics: Log for fraud detection
    logSecurityEvent('rooted_device_detected');
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combine with Other Security Measures
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const comprehensiveSecurityCheck = async () =&amp;gt; {
  const checks = await Promise.all([
    RootJailDetect.isDeviceRooted(),
    checkSSLPinning(),
    validateAppIntegrity(),
    verifyDebuggerAbsence()
  ]);

  return checks.every(check =&amp;gt; check === true);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Server-Side Validation
&lt;/h3&gt;

&lt;p&gt;Never rely solely on client-side checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const authenticateWithSecurityCheck = async (credentials) =&amp;gt; {
  const isRooted = await RootJailDetect.isDeviceRooted();

  // Send security status to backend
  const response = await fetch('/api/auth', {
    method: 'POST',
    body: JSON.stringify({
      ...credentials,
      deviceSecurity: {
        isRooted,
        deviceId: getDeviceId(),
        appIntegrity: getAppSignature()
      }
    })
  });

  // Server makes final decision on access
  return response.json();
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Open Source Forever
&lt;/h2&gt;

&lt;p&gt;This project is and will always remain 100% open source under the MIT license. Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transparency: Security through obscurity doesn't work&lt;/li&gt;
&lt;li&gt;Community: Better detection methods emerge from collaborative effort&lt;/li&gt;
&lt;li&gt;Trust: You can audit every line of code&lt;/li&gt;
&lt;li&gt;Innovation: Fork it, modify it, contribute back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every contribution, no matter how small, makes a difference!&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started Today
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install
npm install react-native-root-jail-detect

# iOS
cd ios &amp;amp;&amp;amp; pod install &amp;amp;&amp;amp; cd ..

# Use
import RootJailDetect from 'react-native-root-jail-detect';
const isRooted = await RootJailDetect.isDeviceRooted();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Building secure mobile apps doesn't have to be complicated or expensive. With react-native-root-jail-detect, you get enterprise-grade security detection in a package smaller than a thumbnail image.&lt;/p&gt;

&lt;p&gt;Whether you're building the next fintech unicorn or a simple app that handles sensitive data, this library provides the peace of mind that comes with knowing your users' device integrity.&lt;/p&gt;

&lt;p&gt;Give it a try, star the repo, and join me in making React Native apps more secure for everyone!&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-native-root-jail-detect" rel="noopener noreferrer"&gt;npm Package&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-root-jail-detect" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-root-jail-detect/blob/master/README.md" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rushikeshpandit/react-native-root-jail-detect/issues" rel="noopener noreferrer"&gt;Issue Tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Found this helpful? Drop a ❤️ on the article and ⭐ on GitHub!&lt;br&gt;
Questions or suggestions? Drop them in the comments below! &lt;/p&gt;

&lt;p&gt;Feel free to reach out to me if you have any questions or need assistance.&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering #DevCommunity #root-detection #jailbreak-detection #mobile-security&lt;br&gt;
 #device-integrity&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>typescript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Mastering React Native with TypeScript: From Basics to Brilliance - Part 3</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Sat, 02 Aug 2025 15:03:53 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/mastering-react-native-with-typescript-from-basics-to-brilliance-part-3-p0m</link>
      <guid>https://forem.com/rushikeshpandit/mastering-react-native-with-typescript-from-basics-to-brilliance-part-3-p0m</guid>
      <description>&lt;p&gt;React Native has come a long way, and with the latest versions offering improved performance and TypeScript-first development, it’s a great time to dive into building robust apps with navigation and API communication in mind.&lt;br&gt;
In this article, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up React Navigation in a TypeScript project&lt;/li&gt;
&lt;li&gt;Working with Stacks and Tabs&lt;/li&gt;
&lt;li&gt;Managing API calls with &lt;code&gt;axios&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Handling loading, error, and data states&lt;/li&gt;
&lt;li&gt;Bonus: Tips for organizing your codebase!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 18+&lt;/li&gt;
&lt;li&gt;React Native CLI or Expo (we'll go with bare React Native here)&lt;/li&gt;
&lt;li&gt;React Native 0.76+&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Basic understanding of React Native components&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Setup React Navigation
&lt;/h2&gt;

&lt;p&gt;First, install the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context react-native-gesture-handler react-native-reanimated
npx pod-install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install the stack and bottom tab navigators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @react-navigation/native-stack @react-navigation/bottom-tabs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;babel.config.js&lt;/code&gt; for reanimated (if not Expo):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: ['react-native-reanimated/plugin'],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Navigation Structure
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;navigation/RootNavigator.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from '../screens/HomeScreen';
import DetailsScreen from '../screens/DetailsScreen';

export type RootStackParamList = {
  Home: undefined;
  Details: { userId: number };
};

const Stack = createNativeStackNavigator&amp;lt;RootStackParamList&amp;gt;();

const RootNavigator = () =&amp;gt; (
  &amp;lt;NavigationContainer&amp;gt;
    &amp;lt;Stack.Navigator initialRouteName="Home"&amp;gt;
      &amp;lt;Stack.Screen name="Home" component={HomeScreen} /&amp;gt;
      &amp;lt;Stack.Screen name="Details" component={DetailsScreen} /&amp;gt;
    &amp;lt;/Stack.Navigator&amp;gt;
  &amp;lt;/NavigationContainer&amp;gt;
);

export default RootNavigator;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Screen Components for Home Screen
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;screens/HomeScreen.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';
import { View, Text, Button, FlatList, ActivityIndicator } from 'react-native';
import axios from 'axios';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { RootStackParamList } from '../navigation/RootNavigator';

type Props = NativeStackScreenProps&amp;lt;RootStackParamList, 'Home'&amp;gt;;

interface User {
  id: number;
  name: string;
}

const HomeScreen: React.FC&amp;lt;Props&amp;gt; = ({ navigation }) =&amp;gt; {
  const [users, setUsers] = useState&amp;lt;User[]&amp;gt;([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState&amp;lt;string | null&amp;gt;(null);

  useEffect(() =&amp;gt; {
    axios.get&amp;lt;User[]&amp;gt;('https://jsonplaceholder.typicode.com/users')
      .then(response =&amp;gt; setUsers(response.data))
      .catch(err =&amp;gt; setError(err.message))
      .finally(() =&amp;gt; setLoading(false));
  }, []);

  if (loading) return &amp;lt;ActivityIndicator /&amp;gt;;
  if (error) return &amp;lt;Text&amp;gt;Error: {error}&amp;lt;/Text&amp;gt;;

  return (
    &amp;lt;FlatList
      data={users}
      keyExtractor={item =&amp;gt; item.id.toString()}
      renderItem={({ item }) =&amp;gt; (
        &amp;lt;View style={{ padding: 10 }}&amp;gt;
          &amp;lt;Text&amp;gt;{item.name}&amp;lt;/Text&amp;gt;
          &amp;lt;Button
            title="View Details"
            onPress={() =&amp;gt; navigation.navigate('Details', { userId: item.id })}
          /&amp;gt;
        &amp;lt;/View&amp;gt;
      )}
    /&amp;gt;
  );
};

export default HomeScreen;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Screen Components for Detail Screen
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;screens/DetailsScreen.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import axios from 'axios';
import { RootStackParamList } from '../navigation/RootNavigator';

type Props = NativeStackScreenProps&amp;lt;RootStackParamList, 'Details'&amp;gt;;

interface UserDetail {
  id: number;
  name: string;
  email: string;
  phone: string;
}

const DetailsScreen: React.FC&amp;lt;Props&amp;gt; = ({ route }) =&amp;gt; {
  const { userId } = route.params;
  const [user, setUser] = useState&amp;lt;UserDetail | null&amp;gt;(null);
  const [loading, setLoading] = useState(true);

  useEffect(() =&amp;gt; {
    axios.get&amp;lt;UserDetail&amp;gt;(`https://jsonplaceholder.typicode.com/users/${userId}`)
      .then(response =&amp;gt; setUser(response.data))
      .finally(() =&amp;gt; setLoading(false));
  }, [userId]);

  if (loading) return &amp;lt;ActivityIndicator /&amp;gt;;
  if (!user) return &amp;lt;Text&amp;gt;No user found&amp;lt;/Text&amp;gt;;

  return (
    &amp;lt;View style={{ padding: 20 }}&amp;gt;
      &amp;lt;Text style={{ fontSize: 18 }}&amp;gt;{user.name}&amp;lt;/Text&amp;gt;
      &amp;lt;Text&amp;gt;{user.email}&amp;lt;/Text&amp;gt;
      &amp;lt;Text&amp;gt;{user.phone}&amp;lt;/Text&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default DetailsScreen;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Organize API Layer (Optional but Recommended)
&lt;/h2&gt;

&lt;p&gt;Create a file &lt;code&gt;api/client.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from 'axios';

const client = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/',
  timeout: 5000,
});

export default client;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then import and use &lt;code&gt;client.get()&lt;/code&gt; instead of &lt;code&gt;axios.get()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure Suggestion
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
  /navigation
    RootNavigator.tsx
  /screens
    HomeScreen.tsx
    DetailsScreen.tsx
  /api
    client.ts
  /types
    index.ts
App.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React Navigation’s TypeScript support makes route safety a breeze.&lt;/li&gt;
&lt;li&gt;Centralizing API calls helps scale and debug faster.&lt;/li&gt;
&lt;li&gt;Handling loading/error/data states improves user experience.&lt;/li&gt;
&lt;li&gt;Organize your folders early—it pays off later!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it for today. In the next part of this series, we’ll explore advanced topics like redux toolkit and it's implementation.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me if you have any questions or need assistance.&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering #DevCommunity&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Mastering React Native with TypeScript: From Basics to Brilliance - Part 2</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Sat, 26 Jul 2025 07:21:13 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/mastering-react-native-with-typescript-from-basics-to-brilliance-part-2-16fa</link>
      <guid>https://forem.com/rushikeshpandit/mastering-react-native-with-typescript-from-basics-to-brilliance-part-2-16fa</guid>
      <description>&lt;p&gt;React Native hooks provide an intuitive way to manage state and side effects in your components. Introduced in React 16.8, hooks allow us to use state and other React features without writing class components, making functional components powerful and more readable.&lt;/p&gt;

&lt;p&gt;In this article, we will explore the most commonly used hooks, how they work, and how you can leverage them in your React Native projects. We’ll also look at how to create custom hooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Hooks?
&lt;/h3&gt;

&lt;p&gt;Hooks are functions that let you “hook into” React state and lifecycle features from function components. They make your code cleaner, easier to understand, and reusable.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useState&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; is one of the most commonly used hooks. It lets you add state to functional components. With &lt;code&gt;useState&lt;/code&gt;, you can create variables that store component-level data and re-render your component whenever that data changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';
import { Text, Button, View } from 'react-native';

const Counter = () =&amp;gt; {
  const [count, setCount] = useState&amp;lt;number&amp;gt;(0);

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;Count: {count}&amp;lt;/Text&amp;gt;
      &amp;lt;Button title="Increase" onPress={() =&amp;gt; setCount(count + 1)} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default Counter;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; takes the initial value (0 in the example) and returns an array containing the current value (&lt;code&gt;count&lt;/code&gt;) and a function to update it (&lt;code&gt;setCount&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is used to perform side effects in function components. It runs after every render by default but can also be customized to run only when specific values change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';

const DataFetcher = () =&amp;gt; {
  const [data, setData] = useState&amp;lt;string | null&amp;gt;(null);

  useEffect(() =&amp;gt; {
    // Simulate fetching data from an API
    const fetchData = async () =&amp;gt; {
      const result = await new Promise((resolve) =&amp;gt; 
        setTimeout(() =&amp;gt; resolve("Fetched Data"), 2000)
      );
      setData(result as string);
    };

    fetchData();
  }, []); // empty array ensures this runs once when the component mounts

  return &amp;lt;View&amp;gt;{data ? &amp;lt;Text&amp;gt;{data}&amp;lt;/Text&amp;gt; : &amp;lt;Text&amp;gt;Loading...&amp;lt;/Text&amp;gt;}&amp;lt;/View&amp;gt;;
};

export default DataFetcher;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; runs after the component renders. In this case, we simulate fetching data, and the effect only runs once because of the empty dependency array &lt;code&gt;[]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useContext&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useContext&lt;/code&gt; allows you to use values from React's Context API. This is helpful for passing data like theme or authentication information without prop drilling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { createContext, useContext } from 'react';
import { Text, View } from 'react-native';

// Create a context
const ThemeContext = createContext('light');

const ThemedComponent = () =&amp;gt; {
  const theme = useContext(ThemeContext);
  return &amp;lt;Text&amp;gt;Current Theme: {theme}&amp;lt;/Text&amp;gt;;
};

const App = () =&amp;gt; (
  &amp;lt;ThemeContext.Provider value="dark"&amp;gt;
    &amp;lt;View&amp;gt;
      &amp;lt;ThemedComponent /&amp;gt;
    &amp;lt;/View&amp;gt;
  &amp;lt;/ThemeContext.Provider&amp;gt;
);

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useContext&lt;/code&gt; allows you to consume the value of the nearest &lt;code&gt;ThemeContext.Provider&lt;/code&gt;, eliminating the need to pass down props manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useReducer&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useReducer&lt;/code&gt; is similar to &lt;code&gt;useState&lt;/code&gt; but is used for more complex state logic. It is often used when the state has multiple transitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useReducer } from 'react';
import { Text, Button, View } from 'react-native';

type Action = { type: 'increment' | 'decrement' };
const reducer = (state: number, action: Action) =&amp;gt; {
  switch (action.type) {
    case 'increment':
      return state + 1;
    case 'decrement':
      return state - 1;
    default:
      return state;
  }
};

const Counter = () =&amp;gt; {
  const [count, dispatch] = useReducer(reducer, 0);

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;Count: {count}&amp;lt;/Text&amp;gt;
      &amp;lt;Button title="Increase" onPress={() =&amp;gt; dispatch({ type: 'increment' })} /&amp;gt;
      &amp;lt;Button title="Decrease" onPress={() =&amp;gt; dispatch({ type: 'decrement' })} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default Counter;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useReducer&lt;/code&gt; takes a reducer function and an initial state, returning the current state and a &lt;code&gt;dispatch&lt;/code&gt; function to trigger state changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useCallback&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useCallback&lt;/code&gt; is used to memoize functions so they aren’t recreated on every render, which can be useful for optimization in child components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useCallback } from 'react';
import { Text, Button, View } from 'react-native';

const ChildComponent = React.memo(({ onClick }: { onClick: () =&amp;gt; void }) =&amp;gt; (
  &amp;lt;Button title="Click me" onPress={onClick} /&amp;gt;
));

const ParentComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  const increment = useCallback(() =&amp;gt; {
    setCount((prev) =&amp;gt; prev + 1);
  }, []); // Function is memoized, won't recreate unless dependencies change

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;Count: {count}&amp;lt;/Text&amp;gt;
      &amp;lt;ChildComponent onClick={increment} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default ParentComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useCallback&lt;/code&gt; returns a memoized version of the &lt;code&gt;increment&lt;/code&gt; function, ensuring it is not recreated unless dependencies change.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useMemo&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt; is used to memoize values instead of functions. It recalculates the value only when dependencies change, improving performance in expensive calculations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useMemo, useState } from 'react';
import { Text, Button, View } from 'react-native';

const ExpensiveComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  const expensiveCalculation = useMemo(() =&amp;gt; {
    // Simulate an expensive computation
    return count * 1000;
  }, [count]);

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Text&amp;gt;Result: {expensiveCalculation}&amp;lt;/Text&amp;gt;
      &amp;lt;Button title="Increase Count" onPress={() =&amp;gt; setCount(count + 1)} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default ExpensiveComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt; ensures the expensive calculation runs only when &lt;code&gt;count&lt;/code&gt; changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useRef&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useRef&lt;/code&gt; is used to persist values across renders without causing a re-render. It’s often used to reference DOM elements or hold mutable values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useRef } from 'react';
import { Button, TextInput, View } from 'react-native';

const InputFocus = () =&amp;gt; {
  const inputRef = useRef&amp;lt;TextInput | null&amp;gt;(null);

  const focusInput = () =&amp;gt; {
    inputRef.current?.focus();
  };

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;TextInput ref={inputRef} style={{ height: 40, borderColor: 'gray', borderWidth: 1 }} /&amp;gt;
      &amp;lt;Button title="Focus Input" onPress={focusInput} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default InputFocus;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useRef&lt;/code&gt; creates a reference to the &lt;code&gt;TextInput&lt;/code&gt; component, allowing us to programmatically control its focus.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;useLayoutEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useLayoutEffect&lt;/code&gt; works similarly to &lt;code&gt;useEffect&lt;/code&gt; but is fired synchronously after all DOM mutations, ensuring your effect runs before the browser paints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useLayoutEffect, useState } from 'react';
import { Text, View } from 'react-native';

const LayoutEffectComponent = () =&amp;gt; {
  const [layout, setLayout] = useState({ width: 0, height: 0 });

  useLayoutEffect(() =&amp;gt; {
    // This effect runs before the browser updates the screen
    setLayout({ width: 100, height: 100 });
  }, []);

  return (
    &amp;lt;View style={{ width: layout.width, height: layout.height }}&amp;gt;
      &amp;lt;Text&amp;gt;Layout size: {layout.width} x {layout.height}&amp;lt;/Text&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

export default LayoutEffectComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useLayoutEffect&lt;/code&gt; is useful for reading layout measurements and synchronizing DOM mutations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Custom Hooks
&lt;/h2&gt;

&lt;p&gt;Custom hooks allow you to extract and reuse logic from components. They are simply functions that use hooks internally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from 'react';

const useFetchData = (url: string) =&amp;gt; {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() =&amp;gt; {
    const fetchData = async () =&amp;gt; {
      const response = await fetch(url);
      const result = await response.json();
      setData(result);
      setLoading(false);
    };
    fetchData();
  }, [url]);

  return { data, loading };
};

export default useFetchData;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now use &lt;code&gt;useFetchData&lt;/code&gt; in any component to fetch data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { Text, View } from 'react-native';
import useFetchData from './useFetchData';

const DataComponent = () =&amp;gt; {
  const { data, loading } = useFetchData('https://jsonplaceholder.typicode.com/todos/1');

  return (
    &amp;lt;View&amp;gt;{loading ? &amp;lt;Text&amp;gt;Loading...&amp;lt;/Text&amp;gt; : &amp;lt;Text&amp;gt;{JSON.stringify(data)}&amp;lt;/Text&amp;gt;}&amp;lt;/View&amp;gt;
  );
};

export default DataComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React hooks, combined with TypeScript, offer a powerful and concise way to manage state and side effects in your React Native apps. By mastering hooks like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, and others, you can write cleaner, more efficient components. Additionally, creating custom hooks allows you to reuse logic across your application.&lt;/p&gt;

&lt;p&gt;That's it for today. In the next part of this series, we’ll explore advanced topics like navigation, animations, and working with APIs.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me if you have any questions or need assistance.&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering #DevCommunity&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>hooks</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Mastering React Native with TypeScript: From Basics to Brilliance - Part 1</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Thu, 09 Jan 2025 14:37:05 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/mastering-react-native-with-typescript-from-basics-to-brilliance-part-1-4a46</link>
      <guid>https://forem.com/rushikeshpandit/mastering-react-native-with-typescript-from-basics-to-brilliance-part-1-4a46</guid>
      <description>&lt;p&gt;Are you ready to dive into the world of mobile app development without mastering two separate languages for iOS and Android? Meet &lt;strong&gt;React Native&lt;/strong&gt;—the game-changing framework from Facebook that lets you build high-performance, cross-platform apps using the language you already love: JavaScript (and in our case, TypeScript)!&lt;/p&gt;

&lt;p&gt;With React Native, you can build apps that look, feel, and perform as a true native app would. No wonder it's powering industry-leading apps like Instagram, Airbnb, and Tesla.&lt;/p&gt;

&lt;p&gt;Kickstarting your journey into the world of React Native 0.76 with TypeScript, we are going to go over what the core building blocks of any application are. Whether you're a curious beginner or an experienced developer seeking to hone your abilities in TypeScript, this guide will get you moving toward mobile development greatness.&lt;/p&gt;

&lt;p&gt;We're covering everything you need to know to build your first app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Core Components include &lt;code&gt;View&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, and &lt;code&gt;ScrollView&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Styling techniques that make your UI pop&lt;/li&gt;
&lt;li&gt;Managing Props and State for dynamic interactions&lt;/li&gt;
&lt;li&gt;Mastering lists with &lt;code&gt;FlatList&lt;/code&gt; for seamless data handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of this series, you’ll not only understand the foundation of React Native but also have practical, real-world code snippets to kickstart your app development journey. Let’s make your dream app a reality—starting now!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Components in React Native
&lt;/h2&gt;

&lt;p&gt;Core components are the basic building blocks of every React Native application. They connect the JavaScript world with the native world, and that is where you get the building blocks to craft amazing user interfaces. Let's take a look at each of them.&lt;/p&gt;

&lt;p&gt;1 . &lt;strong&gt;View&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;View&lt;/code&gt; component is the fundamental container in React Native. It’s used to group and layout other components. Think of it as a &lt;code&gt;div&lt;/code&gt; in web development.&lt;/p&gt;

&lt;p&gt;Example: Creating a Centered Box&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { View, StyleSheet } from 'react-native';

const App = () =&amp;gt; (
  &amp;lt;View style={styles.container}&amp;gt;
    &amp;lt;View style={styles.box} /&amp;gt;
  &amp;lt;/View&amp;gt;
);

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  box: { width: 100, height: 100, backgroundColor: 'blue' },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use &lt;code&gt;flex: 1&lt;/code&gt; to ensure the &lt;code&gt;View&lt;/code&gt; fills the entire screen, and &lt;code&gt;justifyContent&lt;/code&gt; and &lt;code&gt;alignItems&lt;/code&gt; center the box.&lt;/p&gt;

&lt;p&gt;2 . &lt;strong&gt;Text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Text&lt;/code&gt; component is used for rendering text on the screen. It supports various text styles and nested elements.&lt;/p&gt;

&lt;p&gt;Example: Displaying Styled Text&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { Text, StyleSheet } from 'react-native';

const App = () =&amp;gt; (
  &amp;lt;Text style={styles.text}&amp;gt;Hello, React Native with TypeScript!&amp;lt;/Text&amp;gt;
);

const styles = StyleSheet.create({
  text: { fontSize: 20, color: 'purple', textAlign: 'center', marginTop: 20 },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we use &lt;code&gt;fontSize&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, and &lt;code&gt;textAlign&lt;/code&gt; to style the Text component.&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;Image&lt;/code&gt; component is used to display images. It supports both local and remote image sources.&lt;/p&gt;

&lt;p&gt;Example: Displaying a Remote Image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { Image, StyleSheet } from 'react-native';

const App = () =&amp;gt; (
  &amp;lt;Image
    source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
    style={styles.image}
  /&amp;gt;
);

const styles = StyleSheet.create({
  image: { width: 100, height: 100, borderRadius: 10 },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;borderRadius&lt;/code&gt; property gives the image rounded corners.&lt;/p&gt;

&lt;p&gt;4 . &lt;strong&gt;TextInput&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;TextInput&lt;/code&gt; component captures user input. It supports properties like &lt;code&gt;placeholder&lt;/code&gt;, &lt;code&gt;onChangeText&lt;/code&gt;, and &lt;code&gt;value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example: Handling User Input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';
import { TextInput, StyleSheet, View, Text } from 'react-native';

const App = () =&amp;gt; {
  const [input, setInput] = useState&amp;lt;string&amp;gt;('');

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;TextInput
        style={styles.input}
        placeholder="Type here..."
        value={input}
        onChangeText={setInput}
      /&amp;gt;
      &amp;lt;Text&amp;gt;You typed: {input}&amp;lt;/Text&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

const styles = StyleSheet.create({
  container: { padding: 20 },
  input: { borderWidth: 1, borderColor: '#ccc', padding: 10, borderRadius: 5, marginBottom: 10 },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;onChangeText&lt;/code&gt; handler updates the state with the user’s input.&lt;/p&gt;

&lt;p&gt;5 . &lt;strong&gt;TouchableOpacity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;TouchableOpacity&lt;/code&gt; component enables touch interactions with a fading effect.&lt;/p&gt;

&lt;p&gt;Example: Creating a Button&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';

const App = () =&amp;gt; (
  &amp;lt;TouchableOpacity style={styles.button} onPress={() =&amp;gt; alert('Button Pressed!')}&amp;gt;
    &amp;lt;Text style={styles.text}&amp;gt;Press Me&amp;lt;/Text&amp;gt;
  &amp;lt;/TouchableOpacity&amp;gt;
);

const styles = StyleSheet.create({
  button: { backgroundColor: 'blue', padding: 10, borderRadius: 5 },
  text: { color: 'white', textAlign: 'center' },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;onPress&lt;/code&gt; handler triggers an action when the button is tapped.&lt;/p&gt;

&lt;p&gt;6 . &lt;strong&gt;ScrollView&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ScrollView&lt;/code&gt; component allows for scrollable content. It’s ideal for layouts with a small amount of content that won’t require heavy performance optimization.&lt;/p&gt;

&lt;p&gt;Example: Rendering a Scrollable List&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { ScrollView, Text, StyleSheet } from 'react-native';

const App = () =&amp;gt; (
  &amp;lt;ScrollView contentContainerStyle={styles.container}&amp;gt;
    {Array.from({ length: 20 }, (_, i) =&amp;gt; (
      &amp;lt;Text key={i} style={styles.text}&amp;gt;Item {i + 1}&amp;lt;/Text&amp;gt;
    ))}
  &amp;lt;/ScrollView&amp;gt;
);

const styles = StyleSheet.create({
  container: { padding: 10 },
  text: { fontSize: 16, marginVertical: 5 },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we dynamically generate 20 items and render them inside a &lt;code&gt;ScrollView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;7 . &lt;strong&gt;FlatList&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;FlatList&lt;/code&gt; component is designed for rendering large datasets efficiently. It only renders items currently visible on the screen, significantly improving performance.&lt;/p&gt;

&lt;p&gt;Example: Rendering a List&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { FlatList, Text, View, StyleSheet } from 'react-native';

const data = [
  { id: '1', name: 'Item 1' },
  { id: '2', name: 'Item 2' },
  { id: '3', name: 'Item 3' },
];

const App = () =&amp;gt; (
  &amp;lt;FlatList
    data={data}
    keyExtractor={(item) =&amp;gt; item.id}
    renderItem={({ item }) =&amp;gt; (
      &amp;lt;View style={styles.item}&amp;gt;
        &amp;lt;Text style={styles.text}&amp;gt;{item.name}&amp;lt;/Text&amp;gt;
      &amp;lt;/View&amp;gt;
    )}
  /&amp;gt;
);

const styles = StyleSheet.create({
  item: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  text: {
    fontSize: 18,
  },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Difference Between FlatList and ScrollView:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;FlatList&lt;/code&gt; for large, dynamic datasets to optimize performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;ScrollView&lt;/code&gt; for smaller datasets or static content.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Styling in React Native
&lt;/h2&gt;

&lt;p&gt;Styling in React Native is achieved using the &lt;code&gt;StyleSheet&lt;/code&gt; API. It borrows heavily from CSS but is tailored to work with native platforms for optimal performance.&lt;/p&gt;

&lt;p&gt;1 . &lt;strong&gt;StyleSheet API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;StyleSheet&lt;/code&gt; API provides a way to define styles separately and reuse them across components.&lt;/p&gt;

&lt;p&gt;Example: Creating Reusable Styles&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const App = () =&amp;gt; (
  &amp;lt;View style={styles.container}&amp;gt;
    &amp;lt;Text style={styles.text}&amp;gt;Reusable Styles with StyleSheet&amp;lt;/Text&amp;gt;
  &amp;lt;/View&amp;gt;
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f0f0f0',
  },
  text: {
    fontSize: 20,
    color: 'blue',
  },
});

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 . &lt;strong&gt;Flexbox Layout&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React Native employs Flexbox for layout management. Flexbox helps to define the alignment, distribution, and spacing of elements within a container.&lt;/p&gt;

&lt;p&gt;Example: Aligning Items Horizontally&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: 10,
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 . &lt;strong&gt;Platform-Specific Styling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React Native allows platform-specific styles using the &lt;code&gt;Platform&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;Example: Conditional Styling&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Platform, StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  text: {
    fontSize: Platform.OS === 'ios' ? 20 : 18,
    color: Platform.OS === 'ios' ? 'blue' : 'green',
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Props and State Management
&lt;/h2&gt;

&lt;p&gt;1 . &lt;strong&gt;Props&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Props allow you to pass data from a parent component to a child component.&lt;/p&gt;

&lt;p&gt;Example: Custom Greeting Component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { Text } from 'react-native';

const Greeting = ({ name }: { name: string }) =&amp;gt; (
  &amp;lt;Text&amp;gt;Hello, {name}!&amp;lt;/Text&amp;gt;
);

const App = () =&amp;gt; &amp;lt;Greeting name="React Native" /&amp;gt;;

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 . &lt;strong&gt;State Management with &lt;code&gt;useState&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useState&lt;/code&gt; hook is used to manage state in functional components.&lt;/p&gt;

&lt;p&gt;Example: Counter Component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

const Counter = () =&amp;gt; {
  const [count, setCount] = useState&amp;lt;number&amp;gt;(0);

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;Text style={styles.text}&amp;gt;Count: {count}&amp;lt;/Text&amp;gt;
      &amp;lt;Button title="Increase" onPress={() =&amp;gt; setCount(count + 1)} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  text: {
    fontSize: 18,
    marginBottom: 10,
  },
});

export default Counter;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 . &lt;strong&gt;Typing Props with TypeScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using TypeScript ensures type safety when passing props.&lt;/p&gt;

&lt;p&gt;Example: Typing Props&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface GreetingProps {
  name: string;
}

const Greeting = ({ name }: GreetingProps) =&amp;gt; (
  &amp;lt;Text&amp;gt;Hello, {name}!&amp;lt;/Text&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for today. In the next part of this series, we’ll explore advanced topics like navigation, animations, hooks, and working with APIs.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me if you have any questions or need assistance.&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#ReactNative #TypeScript #MobileDevelopment #SoftwareEngineering   #DevCommunity&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Leverage ETS for Shared State in Phoenix</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Mon, 09 Dec 2024 13:45:00 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/leverage-ets-for-shared-state-in-phoenix-2mo8</link>
      <guid>https://forem.com/rushikeshpandit/leverage-ets-for-shared-state-in-phoenix-2mo8</guid>
      <description>&lt;p&gt;When building web applications, managing shared state efficiently is often a challenge. For Elixir developers, &lt;strong&gt;ETS (Erlang Term Storage)&lt;/strong&gt; provides an incredibly powerful tool to tackle this problem. ETS is a robust, in-memory data store built into the Erlang VM, offering fast lookups, concurrent access, and persistence during a process’s lifetime.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll explore &lt;strong&gt;how ETS works&lt;/strong&gt;, &lt;strong&gt;why it’s an excellent choice for shared state in Phoenix applications&lt;/strong&gt;, and demonstrate practical examples with code snippets.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is ETS?
&lt;/h1&gt;

&lt;p&gt;ETS (Erlang Term Storage) is a highly efficient in-memory storage system available in Elixir and Erlang. It supports storing key-value pairs, lists, and tuples and is designed to handle high-performance operations with concurrent reads and writes. ETS tables live as long as the process that owns them, making them ideal for managing temporary or shared state.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Use ETS in Phoenix?
&lt;/h1&gt;

&lt;p&gt;ETS is a great fit for Phoenix applications in scenarios such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Store frequently accessed data, such as API responses or computed results, for quick retrieval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session Management&lt;/strong&gt;: Maintain temporary user session data across requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting&lt;/strong&gt;: Track user activity to enforce API rate limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Data Sharing&lt;/strong&gt;: Share data between processes efficiently.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  ETS Basics
&lt;/h1&gt;

&lt;p&gt;To get started, let’s create and manipulate a simple ETS table. You can create a table using &lt;code&gt;:ets.new/2&lt;/code&gt; and interact with it using functions like &lt;code&gt;:ets.insert/2&lt;/code&gt; and &lt;code&gt;:ets.lookup/2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Creating an ETS table
table = :ets.new(:example_table, [:set, :public])

# Inserting data
:ets.insert(table, {:key, "value"})

# Retrieving data
case :ets.lookup(table, :key) do
  [{:key, value}] -&amp;gt; IO.puts("Found: #{value}")
  [] -&amp;gt; IO.puts("Not found")
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using ETS in Phoenix
&lt;/h1&gt;

&lt;p&gt;Let’s dive into a practical example: caching frequently accessed data in a Phoenix application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. ETS for Caching API Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose you have a Phoenix controller that fetches data from an external API. Instead of fetching the data on every request, you can cache the result in ETS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ETS Cache Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a module to manage your ETS table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyApp.Cache do
  @table :api_cache

  def start_link do
    :ets.new(@table, [:named_table, :set, :public, read_concurrency: true])
    {:ok, %{}}
  end

  def put(key, value) do
    :ets.insert(@table, {key, value})
  end

  def get(key) do
    case :ets.lookup(@table, key) do
      [{^key, value}] -&amp;gt; {:ok, value}
      [] -&amp;gt; :error
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fetching and Caching API Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use this module in your controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyAppWeb.PageController do
  use MyAppWeb, :controller

  alias MyApp.Cache

  def index(conn, _params) do
    data =
      case Cache.get(:api_data) do
        {:ok, cached_data} -&amp;gt;
          cached_data

        :error -&amp;gt;
          # Fetch data from external API
          api_data = fetch_data_from_api()
          Cache.put(:api_data, api_data)
          api_data
      end

    render(conn, "index.html", data: data)
  end

  defp fetch_data_from_api do
    # Simulated API call
    %{key: "value", timestamp: DateTime.utc_now()}
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, subsequent requests to &lt;code&gt;index/2&lt;/code&gt; will retrieve data from the ETS cache instead of making repeated API calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Rate Limiting with ETS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another practical use case is rate limiting. You can use ETS to track how many requests a user has made within a given time window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate Limiter Module&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyApp.RateLimiter do
  @table :rate_limiter

  def start_link do
    :ets.new(@table, [:named_table, :set, :public])
    {:ok, %{}}
  end

  def allow?(user_id, limit \\ 10) do
    case :ets.lookup(@table, user_id) do
      [{^user_id, count}] when count &amp;gt;= limit -&amp;gt;
        false

      [{^user_id, count}] -&amp;gt;
        :ets.insert(@table, {user_id, count + 1})
        true

      [] -&amp;gt;
        :ets.insert(@table, {user_id, 1})
        true
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using the Rate Limiter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Integrate it into a Phoenix controller to enforce limits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyAppWeb.ApiController do
  use MyAppWeb, :controller

  alias MyApp.RateLimiter

  def index(conn, _params) do
    user_id = get_user_id(conn)

    if RateLimiter.allow?(user_id) do
      json(conn, %{message: "Request allowed"})
    else
      conn
      |&amp;gt; put_status(:too_many_requests)
      |&amp;gt; json(%{error: "Rate limit exceeded"})
    end
  end

  defp get_user_id(conn) do
    # Example: extract user ID from session or token
    conn.assigns[:current_user].id
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup ensures that a user cannot exceed the specified request limit, and ETS handles the tracking efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced ETS Tips&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Named Tables&lt;/strong&gt;: Use named tables (&lt;code&gt;[:named_table]&lt;/code&gt;) for global access across processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency Options&lt;/strong&gt;: Use &lt;code&gt;:read_concurrency&lt;/code&gt; and &lt;code&gt;:write_concurrency&lt;/code&gt; for performance optimization in read-heavy or write-heavy scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: Combine ETS with &lt;code&gt;:dets&lt;/code&gt; (Disk ETS) to persist data across application restarts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Limitations of ETS&lt;/strong&gt;&lt;br&gt;
While ETS is powerful, it’s important to be aware of its limitations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Table Lifespan&lt;/strong&gt;: Tables are tied to the lifecycle of their owning process. If the process crashes, the table is lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual Garbage Collection&lt;/strong&gt;: ETS doesn’t automatically manage expired data. You’ll need to implement a cleanup mechanism if necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cluster Awareness&lt;/strong&gt;: ETS is not distributed across nodes in a cluster. For distributed setups, consider using Mnesia or a database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ETS is a fantastic tool for managing shared state in Phoenix applications. Its simplicity and speed make it ideal for caching, rate limiting, and real-time data sharing. However, understanding its limitations is key to using it effectively.&lt;/p&gt;

&lt;p&gt;Have you used ETS in your Phoenix projects? Share your experiences in the comments or let me know what other ETS use cases you'd like to explore!&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you need help.&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#myelixirstatus , #elixir , #phoenixframework&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>elixir</category>
      <category>phoenixframework</category>
    </item>
    <item>
      <title>Harness PubSub for Real-Time Features in Phoenix Framework</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Mon, 02 Dec 2024 13:03:14 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/harness-pubsub-for-real-time-features-in-phoenix-framework-2hk7</link>
      <guid>https://forem.com/rushikeshpandit/harness-pubsub-for-real-time-features-in-phoenix-framework-2hk7</guid>
      <description>&lt;p&gt;When it comes to building real-time web applications, the Phoenix framework is hard to beat. At the heart of its real-time capabilities lies Phoenix.PubSub, a powerful messaging system that allows processes to subscribe to and broadcast messages within an application. Whether you’re building live notifications, collaborative tools, or event-driven systems, PubSub is your go-to tool.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll explore &lt;strong&gt;how Phoenix.PubSub works&lt;/strong&gt;, dive into &lt;strong&gt;practical use cases&lt;/strong&gt;, and demonstrate &lt;strong&gt;step-by-step examples&lt;/strong&gt; to integrate it into your projects.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Phoenix.PubSub?
&lt;/h1&gt;

&lt;p&gt;Phoenix.PubSub is a publish-subscribe mechanism built into the Phoenix framework. It allows you to broadcast messages to multiple subscribers efficiently, enabling real-time communication across your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Publishers:&lt;/strong&gt; Send messages to a specific topic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscribers:&lt;/strong&gt; Listen for messages on topics they are interested in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Topics:&lt;/strong&gt; Strings representing the channel for communication (e.g., &lt;code&gt;"notifications"&lt;/code&gt;, &lt;code&gt;"room:lobby"&lt;/code&gt;).
PubSub is transport-agnostic, meaning it can work seamlessly across distributed systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Why Use PubSub?
&lt;/h1&gt;

&lt;p&gt;PubSub is an excellent fit for scenarios like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Real-time notifications:&lt;/strong&gt; Push updates instantly to users (e.g., alerts, badges).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative tools:&lt;/strong&gt; Enable live edits or actions in shared environments (e.g., Google Docs-style collaboration).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event broadcasting:&lt;/strong&gt; Notify multiple processes of significant events (e.g., user activity).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; Distribute messages across nodes in a clustered environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Setting Up PubSub
&lt;/h1&gt;

&lt;p&gt;PubSub is automatically included in new Phoenix applications, but to use it effectively, let’s break down the setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Configuration&lt;/strong&gt;&lt;br&gt;
Ensure your application’s &lt;code&gt;PubSub&lt;/code&gt; module is defined in &lt;code&gt;lib/my_app/application.ex&lt;/code&gt;. It’s typically added by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      {Phoenix.PubSub, name: MyApp.PubSub}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Broadcasting Messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;Phoenix.PubSub.broadcast/3&lt;/code&gt; to send messages to a specific topic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phoenix.PubSub.broadcast(MyApp.PubSub, "notifications", %{message: "New user signed up!"})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Subscribing to Topics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Processes can subscribe to a topic using &lt;code&gt;Phoenix.PubSub.subscribe/2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phoenix.PubSub.subscribe(MyApp.PubSub, "notifications")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Real-World Example: Notifications System
&lt;/h1&gt;

&lt;p&gt;Let’s build a simple notification system where users receive real-time updates whenever a new notification is added.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the PubSub Integration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Subscribe to Notifications&lt;/strong&gt;&lt;br&gt;
When a LiveView mounts, subscribe the process to the &lt;code&gt;"notifications"&lt;/code&gt; topic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def mount(_params, _session, socket) do
  Phoenix.PubSub.subscribe(MyApp.PubSub, "notifications")
  {:ok, assign(socket, notifications: [])}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Handle Incoming Messages&lt;/strong&gt;&lt;br&gt;
When a message is broadcasted, handle it with &lt;code&gt;handle_info/2&lt;/code&gt; and update the LiveView state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_info(%{message: message}, socket) do
  {:noreply, assign(socket, notifications: [message | socket.assigns.notifications])}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Broadcast Notifications&lt;/strong&gt;&lt;br&gt;
Trigger broadcasts from any part of the app (e.g., a controller or background worker).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def notify_users(message) do
  Phoenix.PubSub.broadcast(MyApp.PubSub, "notifications", %{message: message})
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LiveView Template&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="notifications"&amp;gt;
  &amp;lt;h3&amp;gt;Notifications&amp;lt;/h3&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;%= for notification &amp;lt;- @notifications do %&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;%= notification %&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these steps, users will receive live updates in their notifications list whenever &lt;code&gt;notify_users/1&lt;/code&gt; is called.&lt;/p&gt;

&lt;h1&gt;
  
  
  Advanced Use Case: Collaborative Editing
&lt;/h1&gt;

&lt;p&gt;PubSub shines in collaborative tools. For instance, imagine a real-time collaborative text editor where multiple users edit the same document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broadcasting Edits&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_event("edit", %{"content" =&amp;gt; content}, socket) do
  Phoenix.PubSub.broadcast(MyApp.PubSub, "document:123", %{content: content})
  {:noreply, socket}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Subscribing to Edits&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def mount(_params, _session, socket) do
  Phoenix.PubSub.subscribe(MyApp.PubSub, "document:123")
  {:ok, assign(socket, content: "")}
end

def handle_info(%{content: content}, socket) do
  {:noreply, assign(socket, content: content)}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Testing PubSub
&lt;/h1&gt;

&lt;p&gt;You can test your PubSub implementation easily using &lt;code&gt;iex&lt;/code&gt;. Open multiple &lt;code&gt;iex&lt;/code&gt; sessions and ensure they subscribe to the same topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phoenix.PubSub.subscribe(MyApp.PubSub, "test_topic")

Phoenix.PubSub.broadcast(MyApp.PubSub, "test_topic", %{data: "Hello, PubSub!"})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All subscribers to &lt;code&gt;"test_topic"&lt;/code&gt; should receive the broadcast message.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scaling PubSub Across Nodes
&lt;/h1&gt;

&lt;p&gt;Phoenix.PubSub supports distributed systems out of the box. To enable clustering:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;:libcluster&lt;/code&gt; to your dependencies.&lt;/li&gt;
&lt;li&gt;Configure clustering in &lt;code&gt;config/runtime.exs&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config :libcluster,
  topologies: [
    example: [
      strategy: Cluster.Strategy.Gossip
    ]
  ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start your application on multiple nodes, and messages will seamlessly propagate across them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Phoenix.PubSub is a powerful tool for building real-time features in Elixir applications. Whether you’re creating a simple notification system or scaling to a distributed collaborative environment, PubSub provides the flexibility and performance you need.&lt;/p&gt;

&lt;p&gt;If you’ve built something cool with Phoenix.PubSub, let me know in the comments—I’d love to hear about your experience!&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you need help.&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#myelixirstatus , #elixir , #phoenixframework&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>webdev</category>
      <category>phoenixframework</category>
      <category>pubsub</category>
    </item>
    <item>
      <title>Optimize LiveView Performance with Temporary Assigns</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Tue, 26 Nov 2024 13:23:59 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/optimize-liveview-performance-with-temporary-assigns-21gc</link>
      <guid>https://forem.com/rushikeshpandit/optimize-liveview-performance-with-temporary-assigns-21gc</guid>
      <description>&lt;p&gt;When working with Phoenix LiveView, you often juggle a lot of data while building interactive, real-time web applications. One challenge developers face is managing memory efficiently, especially for components or pages that render frequently changing data. &lt;strong&gt;Temporary assigns&lt;/strong&gt; in LiveView provide a smart way to handle this challenge.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll dive deep into &lt;strong&gt;what temporary assigns are, why you should use them&lt;/strong&gt;, and provide practical examples to help you harness their power effectively.&lt;/p&gt;

&lt;h1&gt;
  
  
  What Are Temporary Assigns?
&lt;/h1&gt;

&lt;p&gt;Temporary assigns are a feature of Phoenix LiveView that lets you specify certain assigns to be reset to their default value after every render. This means LiveView doesn’t persist these values in memory, which can save significant resources when dealing with large or frequently changing data.&lt;/p&gt;

&lt;p&gt;Without temporary assigns, all the assigns in your LiveView process are kept in memory between renders. While this is fine for small, static data, it can quickly add up when you’re working with dynamic content, such as lists, logs, or real-time updates.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Use Temporary Assigns?
&lt;/h1&gt;

&lt;p&gt;Here are a few scenarios where temporary assigns can be particularly helpful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reducing Memory Usage&lt;/strong&gt;: If you have a LiveView that frequently updates large datasets (e.g., a chat app or a live dashboard), temporary assigns prevent stale data from piling up in memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improving Performance&lt;/strong&gt;: By resetting unused data after each render, you reduce the load on your LiveView processes, keeping them lightweight and efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preventing Memory Leaks&lt;/strong&gt;: Long-running LiveView processes with large, unused assigns can inadvertently cause memory leaks. Temporary assigns are a built-in safeguard against this.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Setting Up Temporary Assigns
&lt;/h1&gt;

&lt;p&gt;To enable temporary assigns, use the &lt;code&gt;temporary_assigns&lt;/code&gt; key in the &lt;code&gt;socket&lt;/code&gt;'s &lt;code&gt;assign&lt;/code&gt; function. Here’s a basic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def mount(_params, _session, socket) do
  {:ok, 
   assign(socket, 
     messages: [], 
     temporary_assigns: [messages: []]
   )}
end

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

&lt;/div&gt;



&lt;p&gt;In this example, we’ve marked the &lt;code&gt;messages&lt;/code&gt; assign as temporary. After every render, &lt;code&gt;messages&lt;/code&gt; will reset to an empty list (&lt;code&gt;[]&lt;/code&gt;), regardless of its previous state.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Practical Example: Live Chat with Temporary Assigns
&lt;/h1&gt;

&lt;p&gt;Let’s build a live chat application where messages are sent in real time. Without temporary assigns, the LiveView process would hold onto every single message, leading to bloated memory usage over time. Instead, we’ll use temporary assigns to keep the memory footprint minimal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LiveView Module&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyAppWeb.ChatLive do
  use Phoenix.LiveView

  def mount(_params, _session, socket) do
    {:ok, 
     assign(socket, 
       messages: [], 
       temporary_assigns: [messages: []]
     )}
  end

  def handle_event("send_message", %{"content" =&amp;gt; content}, socket) do
    message = %{content: content, timestamp: DateTime.utc_now()}

    # Append the new message to the messages list
    {:noreply, assign(socket, messages: [message])}
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LiveView Template&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="chat-container"&amp;gt;
  &amp;lt;div id="messages"&amp;gt;
    &amp;lt;%= for message &amp;lt;- @messages do %&amp;gt;
      &amp;lt;div class="message"&amp;gt;
        &amp;lt;p&amp;gt;&amp;lt;%= message.content %&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;small&amp;gt;&amp;lt;%= message.timestamp %&amp;gt;&amp;lt;/small&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;form phx-submit="send_message"&amp;gt;
    &amp;lt;input type="text" name="content" placeholder="Type a message..." required /&amp;gt;
    &amp;lt;button type="submit"&amp;gt;Send&amp;lt;/button&amp;gt;
  &amp;lt;/form&amp;gt;
&amp;lt;/div&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@messages&lt;/code&gt; is marked as a temporary assign, so it resets to &lt;code&gt;[]&lt;/code&gt; after each render.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;messages&lt;/code&gt; list is only populated during the render lifecycle, reducing the memory overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Testing Temporary Assigns in Action
&lt;/h1&gt;

&lt;p&gt;To see the difference temporary assigns make, you can log the state of the &lt;code&gt;socket&lt;/code&gt; after each event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_event("send_message", %{"content" =&amp;gt; content}, socket) do
  message = %{content: content, timestamp: DateTime.utc_now()}
  updated_socket = assign(socket, messages: [message])

  IO.inspect(updated_socket.assigns, label: "Socket Assigns After Render")

  {:noreply, updated_socket}
end

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

&lt;/div&gt;



&lt;p&gt;Run the application and observe how &lt;code&gt;@messages&lt;/code&gt; is reset to its default state (&lt;code&gt;[]&lt;/code&gt;) after each render.&lt;/p&gt;

&lt;h1&gt;
  
  
  When Not to Use Temporary Assigns
&lt;/h1&gt;

&lt;p&gt;While temporary assigns are incredibly powerful, they aren’t always the right tool. Avoid using them if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You need persistent data&lt;/strong&gt;: For example, user session data or application state that shouldn’t be lost between renders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cost of re-fetching data is too high&lt;/strong&gt;: If the data comes from an external API or a complex computation, temporary assigns might introduce unnecessary overhead.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Advanced Use Cases
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Combining Temporary Assigns with Streams&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For large datasets that change incrementally (e.g., logs or paginated results), combine temporary assigns with LiveView streams for optimal performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def mount(_params, _session, socket) do
  {:ok, 
   socket
   |&amp;gt; assign(:logs, [])
   |&amp;gt; stream(:logs, [])
   |&amp;gt; assign(temporary_assigns: [logs: []])
  }
end

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

&lt;/div&gt;



&lt;p&gt;This approach ensures that only the current batch of logs is in memory, while older logs are efficiently managed using streams.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Temporary assigns in Phoenix LiveView are an elegant solution to a common problem in real-time web development: managing memory while maintaining interactivity. By understanding when and how to use them, you can build scalable, performant applications without sacrificing user experience.&lt;/p&gt;

&lt;p&gt;If you’ve used temporary assigns in your projects or have tips to share, let me know in the comments—I’d love to hear how you’re optimizing your LiveView apps!&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you need help.&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#myelixirstatus , #elixir , #phoenixframework&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>elixir</category>
      <category>phoenixframework</category>
      <category>liveview</category>
    </item>
    <item>
      <title>Understanding Hooks in the Phoenix Framework</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Mon, 30 Sep 2024 14:25:12 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/understanding-hooks-in-the-phoenix-framework-3dih</link>
      <guid>https://forem.com/rushikeshpandit/understanding-hooks-in-the-phoenix-framework-3dih</guid>
      <description>&lt;p&gt;Hello everyone,&lt;/p&gt;

&lt;p&gt;I hope this message finds you in good spirits. In the current piece, we will focus our attention on the concept of hooks in the Phoneix app.&lt;/p&gt;

&lt;p&gt;Phoenix Framework Hooks are a great extension of LiveView improvements by executing custom JavaScript on the client side. It enables you to use JavaScript directly, which isn’t feasible or efficient only with live view, where there is a need for dynamic behaviour.&lt;/p&gt;

&lt;p&gt;In the Phoenix Framework context, hooks are simply a method that allows triggering JavaScript when a given element of the LiveView is rendered or updated in the DOM.&lt;/p&gt;

&lt;p&gt;Hooks help in smoothly adding any form of interaction with the LiveView that is already painted on the browser. Most of the interaction with Phoenix LiveView is that the contents are rendered on the server side. However, there are cases such as when the UI is animated, or some other javascript library is turning up that some actions on the front end have to take place in real-time to perform certain actions on the user interface.&lt;/p&gt;

&lt;p&gt;Importantly, while Phoenix LiveView efficiently handles state and UI updates from the server, there are cases when client-side code is required. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Third-Party Libraries&lt;/strong&gt;: Imagine you're integrating a charting library like Chart.js or a UI toolkit that requires client-side code to initialise after a LiveView page is loaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom DOM Manipulation&lt;/strong&gt;: Sometimes, you need to apply JavaScript directly to an element after it's rendered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Animations&lt;/strong&gt;: There are cases where animations triggered by JavaScript can enhance the user experience, such as sliding in a notification bar or creating modal popups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handling Real-Time Events&lt;/strong&gt;: For real-time event handling beyond what Phoenix Channels or LiveView directly provide, you may need JavaScript to react to specific events in the front end.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the introduction of Hooks, it has become possible to enhance client-side functionalities without losing the merits of server-side rendered pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Support For Hooks To Phoenix
&lt;/h2&gt;

&lt;p&gt;Hooks primarily are instantiated in the LiveSocket object in JavaScript. In your LiveView templates, you include hooks to certain elements and every time that element gets rendered or is updated, that hook will run its Javascript code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Hook in JavaScript
&lt;/h3&gt;

&lt;p&gt;To get started, create a hook in a javascript file that is prepared to cover LiveView features.&lt;/p&gt;

&lt;p&gt;Usually, the importation of the LiveSocket and the initialisation of the custom hooks are found in the ‘assets/js/app.js’ file in Phoenix.&lt;br&gt;
Here’s how you can define a simple hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let Hooks = {};

Hooks.ExampleHook = {
  mounted() {
    console.log("Hook mounted!");
    // Your logic when the hook is attached to an element
  },
  updated() {
    console.log("Hook updated!");
    // Logic when the DOM updates with this element
  },
  destroyed() {
    console.log("Hook destroyed!");
    // Cleanup logic when the element is removed
  }
};

let liveSocket = new LiveSocket("/live", Socket, {
  hooks: Hooks
});

liveSocket.connect();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example defines a hook named ExampleHook that can respond to lifecycle events such as &lt;code&gt;mounted()&lt;/code&gt;, &lt;code&gt;updated()&lt;/code&gt;, and &lt;code&gt;destroyed()&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mounted()&lt;/code&gt;: Executes when the element is first rendered.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updated()&lt;/code&gt;: Executes when the element updates (such as when LiveView re-renders).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;destroyed()&lt;/code&gt;: Executes when the element is removed from the DOM.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Use the Hook in Your LiveView Template
&lt;/h3&gt;

&lt;p&gt;After defining your hook in JavaScript, you need to attach it to an element in your LiveView template. You can do this using the &lt;code&gt;phx-hook&lt;/code&gt; attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="example" phx-hook="ExampleHook"&amp;gt;
  &amp;lt;!-- Your dynamic content goes here --&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;phx-hook&lt;/code&gt; attribute connects the HTML element to the &lt;code&gt;ExampleHook&lt;/code&gt; you defined in JavaScript. When this element is rendered or updated by LiveView, the appropriate JavaScript lifecycle methods (e.g., &lt;code&gt;mounted&lt;/code&gt;, &lt;code&gt;updated&lt;/code&gt;, etc.) will be triggered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add Custom Behavior
&lt;/h3&gt;

&lt;p&gt;Let’s add some custom behaviour to the hook to demonstrate its capabilities. For example, let's say you want to focus an input field as soon as it is mounted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hooks.FocusInput = {
  mounted() {
    this.el.focus();
  },
  updated() {
    this.el.focus();
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;FocusInput&lt;/code&gt; hook will focus the input field whenever it is mounted or updated.&lt;/p&gt;

&lt;p&gt;Now, attach this hook to your LiveView template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;input type="text" phx-hook="FocusInput" placeholder="Focus me!"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When this input field is rendered, it will automatically receive focus, creating a smooth user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing a Chart.js Hook
&lt;/h2&gt;

&lt;p&gt;For a more advanced example, use hooks to integrate a charting library such as &lt;strong&gt;Chart.js&lt;/strong&gt; into a LiveView page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Hook in app.js.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hooks.Chart = {
  mounted() {
    let ctx = this.el.getContext('2d');
    this.chart = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
          label: '# of Votes',
          data: [12, 19, 3, 5, 2, 3],
          backgroundColor: 'rgba(255, 99, 132, 0.2)',
          borderColor: 'rgba(255, 99, 132, 1)',
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          y: {
            beginAtZero: true
          }
        }
      }
    });
  },
  updated() {
    this.chart.update();
  },
  destroyed() {
    this.chart.destroy();
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Attach the Hook in Your Template
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;canvas id="myChart" phx-hook="Chart" width="400" height="400"&amp;gt;&amp;lt;/canvas&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, whenever this &lt;code&gt;canvas&lt;/code&gt; element is rendered by LiveView, the chart will be drawn using Chart.js.&lt;/p&gt;

&lt;p&gt;That's it for the day. In the next part, we will go through some more concepts of the Phoenix framework.&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you need help.&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#myelixirstatus , #elixir , #phoenixframework&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>hook</category>
    </item>
    <item>
      <title>Mastering Phoenix Framework - Part 3</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Mon, 19 Aug 2024 14:17:55 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/mastering-phoenix-framework-part-3-5go8</link>
      <guid>https://forem.com/rushikeshpandit/mastering-phoenix-framework-part-3-5go8</guid>
      <description>&lt;p&gt;Hi folks,&lt;/p&gt;

&lt;p&gt;I hope you are doing well. In this blog, we will look at some essential concepts of the Phoenix app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Live View
&lt;/h1&gt;

&lt;p&gt;To create a live view we need to enter the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix phx.gen.live Accounts User users name:string age:integer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first argument is the context module, which serves as an API boundary for related resources. If the context already exists, it will be augmented with functions for the new resource.&lt;/p&gt;

&lt;p&gt;The second argument is the schema module, which maps database fields to an Elixir struct.&lt;/p&gt;

&lt;p&gt;The remaining arguments are the schema module's plural name (used as the table name) and an optional list of attributes with their names and types.&lt;/p&gt;

&lt;p&gt;Check out the sample code for live view.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/my_app_web/live/my_live_view.ex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyAppWeb.MyLiveView do
  use MyAppWeb, :live_view

  def render(assigns) do
    ~H"""
    &amp;lt;div&amp;gt;
      Hi from Live View.
    &amp;lt;/div&amp;gt;
    """
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our live view is ready, so we need to add it to our router to use it. To do this, add the following code to your &lt;code&gt;router.ex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scope "/", MyAppWeb do
    pipe_through :browser

    live "/", MyLiveView
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, visit &lt;code&gt;http://localhost:4000/&lt;/code&gt; to see the live view in action.&lt;/p&gt;

&lt;h1&gt;
  
  
  Live Component
&lt;/h1&gt;

&lt;p&gt;To create a live component we need to create a new file named my_component.ex in the following directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/my_app_web/live/my_component.ex&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add the following content in the above file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyAppWeb.MyComponent do
  use MyAppWeb, :live_component

  def render(assigns) do
    ~H"""
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;&amp;lt;%= @title %&amp;gt;&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;&amp;lt;%= @description %&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
    """
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, this component expects 2 values such as &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;. We need to pass these 2 values whenever we want to consume this component in our live view. To do this, we need to update our live view as follows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/my_app_web/live/my_live_view.ex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defmodule MyAppWeb.MyLiveView do
  use MyAppWeb, :live_view
  alias MyAppWeb.MyComponent

  def render(assigns) do
    ~H"""
    &amp;lt;div&amp;gt;
      &amp;lt;.live_component module={MyComponent}
        id= "my-component"
        title={@title}
        description={@description}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
    """
  end

  def mount(_params, _session, socket) do
    {:ok, assign(socket, title: "Hello, World!", description: "This is a description.")}
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The live_component function is used to render MyAppWeb.MyComponent.&lt;/li&gt;
&lt;li&gt;The module attribute is used to specify the component module.&lt;/li&gt;
&lt;li&gt;The id is required and must be unique for each instance of the component.&lt;/li&gt;
&lt;li&gt;title and description are passed as assigns to the component using {} syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Access the Data in the Component:
&lt;/h3&gt;

&lt;p&gt;Inside our live component's render function, we can access the passed data using @title and @description assigns.&lt;/p&gt;

&lt;h1&gt;
  
  
  Navigation
&lt;/h1&gt;

&lt;p&gt;There are 2 types of navigation we are using in the Phoenix Framework.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server-side navigation&lt;/li&gt;
&lt;li&gt;Client-side navigation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's take a look at them one by one.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Server-side navigation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  - &lt;code&gt;redirect/2&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Sends redirect response to the given URL. For security, :to only accept paths. Use the :external option to redirect to any URL. The response will be sent with the status code defined within the connection, via Plug.Conn.put_status/2. If no status code is set, a 302 response is sent.&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redirect(conn, to: "/login")

redirect(conn, external: "https://elixir-lang.org")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  - &lt;code&gt;push_navigate/2&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The current LiveView will be shut down and a new one will be mounted in its place, without reloading the whole page. This can also be used to remount the same LiveView, in case you want to start fresh. &lt;/p&gt;

&lt;h4&gt;
  
  
  Option
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;:to&lt;/code&gt; - the required path to link to. It must always be a local path&lt;br&gt;
&lt;code&gt;:replace&lt;/code&gt; - the flag to replace the current history or push a new state. Defaults false.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:noreply, push_navigate(socket, to: "/")}
{:noreply, push_navigate(socket, to: "/", replace: true)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  - &lt;code&gt;push_patch/2&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When navigating to the current LiveView, handle_params/3 is immediately invoked to handle the change of params and URL state. Then the new state is pushed to the client, without reloading the whole page while also maintaining the current scroll position. &lt;/p&gt;

&lt;h4&gt;
  
  
  Option
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;:to&lt;/code&gt; - the required path to link to. It must always be a local path&lt;br&gt;
&lt;code&gt;:replace&lt;/code&gt; - the flag to replace the current history or push a new state. Defaults false.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:noreply, push_patch(socket, to: "/")}
{:noreply, push_patch(socket, to: "/", replace: true)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Client-side navigation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  - &lt;code&gt;link/1&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Generates a link to a given route. To navigate across pages, using traditional browser navigation, use the href attribute. To patch the current LiveView or navigate across LiveViews, use the patch and navigate respectively.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Attributes&lt;/code&gt;&lt;br&gt;
&lt;code&gt;navigate (:string)&lt;/code&gt; - Navigates from a LiveView to a new LiveView. The browser page is kept, but a new LiveView process is mounted and its content on the page is reloaded. It is only possible to navigate between LiveViews declared under the same router Phoenix.LiveView.Router.live_session/3. Otherwise, a full browser redirect is used.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;patch (:string)&lt;/code&gt; - Patches the current LiveView. The handle_params callback of the current LiveView will be invoked and the minimum content will be sent over the wire, as any other LiveView diff.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;href (:any)&lt;/code&gt; - Uses traditional browser navigation to the new location. This means the whole page is reloaded on the browser.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;replace (:boolean)&lt;/code&gt; - When using :patch or :navigate, should the browser's history be replaced with pushState?&lt;/p&gt;

&lt;p&gt;Defaults to false.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;method (:string)&lt;/code&gt; - The HTTP method to use with the link. This is intended for usage outside of LiveView and therefore only works with the href={...} attribute. It has no effect on the patch and navigate instructions. In case the method does not work, the link is generated inside the form which sets the proper information. To submit the form, JavaScript must be enabled in the browser. Defaults to &lt;code&gt;get&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;csrf_token (:any)&lt;/code&gt; - A boolean or custom token to use for links with an HTTP method other than get. Defaults to true. Global attributes are accepted. Additional HTML attributes are added to the tag. Supports all globals plus: ["download", "hreflang", "referrerpolicy", "rel", "target", "type"].&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Slots&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;inner_block (required)&lt;/code&gt; - The content rendered inside of the a tag.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;.link href="/"&amp;gt;Regular anchor link&amp;lt;/.link&amp;gt;

&amp;lt;.link navigate={~p"/"} class="underline"&amp;gt;home&amp;lt;/.link&amp;gt;

&amp;lt;.link navigate={~p"/?sort=asc"} replace={false}&amp;gt;
  Sort By Price
&amp;lt;/.link&amp;gt;

&amp;lt;.link patch={~p"/details"}&amp;gt;view details&amp;lt;/.link&amp;gt;

&amp;lt;.link href={URI.parse("https://elixir-lang.org")}&amp;gt;hello&amp;lt;/.link&amp;gt;

&amp;lt;.link href="/the_world" method="delete" data-confirm="Really?"&amp;gt;delete&amp;lt;/.link&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for the day. In the next part, we will go through some more concepts of the Phoenix framework.&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you need help.&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit-646834100/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit-646834100/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#myelixirstatus , #liveviewnative , #dockyard , #elixir , #phoenixframework&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenixframework</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Mastering Phoenix Framework - Part 2</title>
      <dc:creator>Rushikesh Pandit</dc:creator>
      <pubDate>Mon, 12 Aug 2024 13:40:56 +0000</pubDate>
      <link>https://forem.com/rushikeshpandit/mastering-phoenix-framework-part-2-5hkb</link>
      <guid>https://forem.com/rushikeshpandit/mastering-phoenix-framework-part-2-5hkb</guid>
      <description>&lt;p&gt;Hi All,&lt;/p&gt;

&lt;p&gt;This blog is dedicated to the directory structure for the Phoenix Framework application.&lt;/p&gt;

&lt;p&gt;Checkout my previous blogs here, if you want to know more about Phoenix Framework Application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/rushikeshpandit/mastering-phoenix-framework-introduction-580b"&gt;Mastering Phoenix Framework - Introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/rushikeshpandit/mastering-phoenix-framework-introduction-580b"&gt;Mastering Phoenix Framework - Part 1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, I think we should start with today's topic. Your Phoenix Framework application's directory structure looks similar to the one shown below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Directory structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/my_phoenix_app
├── /assets
│   ├── /js
│   ├── /css
│   └── /static
├── /config
│   ├── config.exs
│   ├── dev.exs
│   ├── prod.exs
│   └── test.exs
├── /deps
├── /lib
│   ├── /my_phoenix_app
│   └── /my_phoenix_app_web
│       ├── /controllers
│       ├── /templates
│       ├── /channels
│       ├── /views
│       ├── /live
│       ├── router.ex
│       └── endpoint.ex
├── /priv
│   ├── /static
│   └── /repo
├── /test
│   ├── /my_phoenix_app_web
│   └── /support
└── mix.exs

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

&lt;/div&gt;



&lt;p&gt;Let's take a detailed look at the directory structure.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/assets&lt;/code&gt;: Contains front-end assets like JavaScript, CSS, images, and other static files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/js: JavaScript files.&lt;/li&gt;
&lt;li&gt;/css: CSS files.&lt;/li&gt;
&lt;li&gt;/static: Static files such as images.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/config&lt;/code&gt;: Configuration files for the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;config.exs: Main configuration file.&lt;/li&gt;
&lt;li&gt;dev.exs: Configuration specific to the development environment.&lt;/li&gt;
&lt;li&gt;prod.exs: Configuration specific to the production environment.&lt;/li&gt;
&lt;li&gt;test.exs: Configuration specific to the test environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/deps&lt;/code&gt;: Dependencies managed by Mix, Elixir's build tool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/lib&lt;/code&gt;: The main directory for your application's code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;/lib/my_phoenix_app: Your application code, including contexts and business logic.&lt;/li&gt;
&lt;li&gt;/lib/my_phoenix_app_web: The web interface of your application.

&lt;ul&gt;
&lt;li&gt;/controllers: Controllers handling HTTP requests and responses.&lt;/li&gt;
&lt;li&gt;/templates: Templates for rendering HTML views.&lt;/li&gt;
&lt;li&gt;/channels: WebSocket channels for real-time features.&lt;/li&gt;
&lt;li&gt;/views: View modules that render templates.&lt;/li&gt;
&lt;li&gt;/live: LiveView modules for real-time updates without JavaScript.&lt;/li&gt;
&lt;li&gt;/router.ex: Defines routes for the application.&lt;/li&gt;
&lt;li&gt;/endpoint.ex: Endpoint configuration for handling requests.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/priv&lt;/code&gt;: Contains private files used by the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/priv/static: Compiled static assets.&lt;/li&gt;
&lt;li&gt;/priv/repo: Database-related files, including migrations and seeds.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;/test&lt;/code&gt;: Test files for the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/test/my_phoenix_app_web: Tests for the web interface.&lt;/li&gt;
&lt;li&gt;/test/support: Helper modules and configuration for tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;mix.exs&lt;/code&gt;: The main build configuration file for the project.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it for the day. I hope you have enjoyed this blog. In the next part, we will go through some more concepts of the Phoenix framework.&lt;/p&gt;

&lt;p&gt;If you have any suggestions/doubts, feel free to reach out via one of the following methods.&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/rushikesh-pandit/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rushikesh-pandit/&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/rushikeshpandit" rel="noopener noreferrer"&gt;https://github.com/rushikeshpandit&lt;/a&gt;&lt;br&gt;
Portfolio: &lt;a href="https://www.rushikeshpandit.in" rel="noopener noreferrer"&gt;https://www.rushikeshpandit.in&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;#myelixirstatus , #liveviewnative , #dockyard , #elixir , #phoenixframework&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
    </item>
  </channel>
</rss>
