<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: noman akram</title>
    <description>The latest articles on DEV Community by noman akram (@noman_akram_6c329a67f88ca).</description>
    <link>https://dev.to/noman_akram_6c329a67f88ca</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%2F3670121%2Ffa3f7b23-568e-4243-8164-de24875e2e1d.jpg</url>
      <title>DEV Community: noman akram</title>
      <link>https://dev.to/noman_akram_6c329a67f88ca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/noman_akram_6c329a67f88ca"/>
    <language>en</language>
    <item>
      <title>Before you think "my users always have WiFi," consider this</title>
      <dc:creator>noman akram</dc:creator>
      <pubDate>Tue, 30 Dec 2025 07:27:16 +0000</pubDate>
      <link>https://dev.to/noman_akram_6c329a67f88ca/before-you-think-my-users-always-have-wifi-consider-this-2gjn</link>
      <guid>https://dev.to/noman_akram_6c329a67f88ca/before-you-think-my-users-always-have-wifi-consider-this-2gjn</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/noman_akram_6c329a67f88ca" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3670121%2Ffa3f7b23-568e-4243-8164-de24875e2e1d.jpg" alt="noman_akram_6c329a67f88ca"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/noman_akram_6c329a67f88ca/building-offline-first-react-native-apps-11de" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Building Offline-First React Native Apps&lt;/h2&gt;
      &lt;h3&gt;noman akram ・ Dec 30&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#reactnative&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#mobile&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#android&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>mobile</category>
      <category>android</category>
    </item>
    <item>
      <title>Building Offline-First React Native Apps</title>
      <dc:creator>noman akram</dc:creator>
      <pubDate>Tue, 30 Dec 2025 07:26:01 +0000</pubDate>
      <link>https://dev.to/noman_akram_6c329a67f88ca/building-offline-first-react-native-apps-11de</link>
      <guid>https://dev.to/noman_akram_6c329a67f88ca/building-offline-first-react-native-apps-11de</guid>
      <description>&lt;p&gt;Your app works perfectly in the office.&lt;br&gt;
Then your user takes the subway. Opens your app. Sees a spinner.&lt;br&gt;
Nothing happens. They close it. Maybe forever.&lt;br&gt;
&lt;strong&gt;The fix is simpler than you think.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Your users are in elevators, basements, airplanes, rural areas, or just have bad signal.&lt;br&gt;
If your app shows "No Internet Connection" and stops working, you're losing people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Simple Solution&lt;/strong&gt;&lt;br&gt;
You need three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Know when offline - Detect network status&lt;/li&gt;
&lt;li&gt;Save data locally - Show something useful&lt;/li&gt;
&lt;li&gt;Sync when back online - Send queued actions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's build it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Detect Network Status
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @react-native-community/netinfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create 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;import NetInfo from '@react-native-community/netinfo';
import { useState, useEffect } from 'react';

export const useOnline = () =&amp;gt; {
  const [isOnline, setIsOnline] = useState(true);

  useEffect(() =&amp;gt; {
    const unsubscribe = NetInfo.addEventListener(state =&amp;gt; {
      setIsOnline(state.isConnected);
    });
    return unsubscribe;
  }, []);

  return isOnline;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you know when to show cached data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Cache API Responses
&lt;/h2&gt;

&lt;p&gt;When your API returns data, save it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fetchReports = async () =&amp;gt; {
  try {
    const response = await fetch('/api/reports');
    const data = await response.json();

    // Save for offline use
    await AsyncStorage.setItem('reports', JSON.stringify(data));
    return data;

  } catch (error) {
    // Network failed - use cache
    const cached = await AsyncStorage.getItem('reports');
    return cached ? JSON.parse(cached) : [];
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Online: Fresh data from API&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offline: Last saved data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User always sees something&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Show Users What's Happening
&lt;/h2&gt;

&lt;p&gt;Don't make them guess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ReportsScreen = () =&amp;gt; {
  const [reports, setReports] = useState([]);
  const isOnline = useOnline();

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

  return (
    &amp;lt;View&amp;gt;
      {!isOnline &amp;amp;&amp;amp; (
        &amp;lt;View style={styles.banner}&amp;gt;
          &amp;lt;Text&amp;gt;📴 Offline - Showing saved data&amp;lt;/Text&amp;gt;
        &amp;lt;/View&amp;gt;
      )}

      &amp;lt;FlatList data={reports} ... /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple banner. Users know what they're seeing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Queue Offline Actions
&lt;/h2&gt;

&lt;p&gt;When users create something offline, save it and sync later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const submitReport = async (data) =&amp;gt; {
  if (!isOnline) {
    // Save locally
    await AsyncStorage.setItem('pending_report', JSON.stringify(data));
    Alert.alert('Saved offline. Will sync when online.');
    return;
  }

  // Normal API call
  await fetch('/api/reports', {
    method: 'POST',
    body: JSON.stringify(data),
  });
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Auto-Sync When Online
&lt;/h2&gt;

&lt;p&gt;Send queued data when connection returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  NetInfo.addEventListener(state =&amp;gt; {
    if (state.isConnected) {
      syncPendingData(); // Send saved actions
    }
  });
}, []);

const syncPendingData = async () =&amp;gt; {
  const pending = await AsyncStorage.getItem('pending_report');

  if (pending) {
    await fetch('/api/reports', {
      method: 'POST',
      body: pending,
    });

    await AsyncStorage.removeItem('pending_report');
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real Example: Medical Records App
&lt;/h2&gt;

&lt;p&gt;Imagine you're building a medical records app. Patients need to access their lab reports, but many live in areas with poor connectivity.&lt;br&gt;
&lt;strong&gt;Here's how offline support helps:&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;const MedicalRecordsScreen = () =&amp;gt; {
  const [records, setRecords] = useState([]);
  const isOnline = useOnline();

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

  const loadRecords = async () =&amp;gt; {
    // Load cache first (instant display)
    const cached = await AsyncStorage.getItem('medical_records');
    if (cached) setRecords(JSON.parse(cached));

    // Then fetch fresh if online
    if (isOnline) {
      try {
        const fresh = await fetch('/api/records').then(r =&amp;gt; r.json());
        setRecords(fresh);
        await AsyncStorage.setItem('medical_records', JSON.stringify(fresh));
      } catch (error) {
        console.log('Using cached data');
      }
    }
  };

  return (
    &amp;lt;View&amp;gt;
      {!isOnline &amp;amp;&amp;amp; (
        &amp;lt;View style={styles.offlineBanner}&amp;gt;
          &amp;lt;Text&amp;gt;📴 Offline Mode&amp;lt;/Text&amp;gt;
        &amp;lt;/View&amp;gt;
      )}
      &amp;lt;FlatList 
        data={records}
        renderItem={({ item }) =&amp;gt; &amp;lt;RecordCard record={item} /&amp;gt;}
      /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What users get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant access to their records (200ms from cache)&lt;/li&gt;
&lt;li&gt;Works in areas with no signal&lt;/li&gt;
&lt;li&gt;Fresh data syncs automatically when online&lt;/li&gt;
&lt;li&gt;No frustrating error screens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This same pattern works for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shopping apps (cached products)&lt;/li&gt;
&lt;li&gt;News apps (saved articles)&lt;/li&gt;
&lt;li&gt;Todo apps (local tasks)&lt;/li&gt;
&lt;li&gt;Social apps (cached feed)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Checklist
&lt;/h2&gt;

&lt;p&gt;Before shipping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show offline indicator&lt;/li&gt;
&lt;li&gt;Cache important data&lt;/li&gt;
&lt;li&gt;Queue offline actions&lt;/li&gt;
&lt;li&gt;Auto-sync when online&lt;/li&gt;
&lt;li&gt;Test in airplane mode&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't do this:&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;if (!isOnline) {
  throw new Error('No internet');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Do this:&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;if (!isOnline) {
  return getCachedData();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When NOT to Cache
&lt;/h2&gt;

&lt;p&gt;Some data shouldn't be cached:&lt;/p&gt;

&lt;p&gt;❌ Banking transactions&lt;br&gt;&lt;br&gt;
❌ Live sports scores&lt;br&gt;&lt;br&gt;
❌ Stock prices&lt;br&gt;&lt;br&gt;
❌ Password reset tokens  &lt;/p&gt;

&lt;p&gt;For these, show "Requires internet connection" and don't fake it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Offline support is three small changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cache responses&lt;/li&gt;
&lt;li&gt;Queue actions&lt;/li&gt;
&lt;li&gt;Tell users what's happening&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your app doesn't need perfect WiFi.&lt;br&gt;
It needs to work when WiFi isn't perfect.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; Add NetInfo to your app today. Cache one API response. See the difference.&lt;/p&gt;

&lt;p&gt;What are you building? Drop a comment.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>mobile</category>
      <category>android</category>
    </item>
    <item>
      <title>Animated Dark/Light Mode in React Native: The iPhone Way</title>
      <dc:creator>noman akram</dc:creator>
      <pubDate>Mon, 22 Dec 2025 09:19:25 +0000</pubDate>
      <link>https://dev.to/noman_akram_6c329a67f88ca/-2f0i</link>
      <guid>https://dev.to/noman_akram_6c329a67f88ca/-2f0i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/noman_akram_6c329a67f88ca" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3670121%2Ffa3f7b23-568e-4243-8164-de24875e2e1d.jpg" alt="noman_akram_6c329a67f88ca"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/noman_akram_6c329a67f88ca/animated-darklight-mode-in-react-native-the-iphone-way-1j17" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Animated Dark/Light Mode in React Native: The iPhone Way&lt;/h2&gt;
      &lt;h3&gt;noman akram ・ Dec 22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#themes&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#reactnative&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>themes</category>
      <category>reactnative</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Animated Dark/Light Mode in React Native: The iPhone Way</title>
      <dc:creator>noman akram</dc:creator>
      <pubDate>Mon, 22 Dec 2025 09:19:07 +0000</pubDate>
      <link>https://dev.to/noman_akram_6c329a67f88ca/animated-darklight-mode-in-react-native-the-iphone-way-1j17</link>
      <guid>https://dev.to/noman_akram_6c329a67f88ca/animated-darklight-mode-in-react-native-the-iphone-way-1j17</guid>
      <description>&lt;p&gt;After implementing dark mode in 50+ React Native apps, I've learned that users expect iPhone-level smooth transitions. Here's how to build it.&lt;br&gt;
The reality: Most apps just flip colors instantly. iPhone animates beautifully. Your app should too.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Animated Theme Switching Matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bad dark mode (what 90% of apps do):&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;// Instant jarring switch
setTheme(theme === 'light' ? 'dark' : 'light');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Flash of wrong colors, harsh transition, feels cheap.&lt;br&gt;
Good dark mode (iPhone way):&lt;/p&gt;

&lt;p&gt;Smooth color transitions&lt;br&gt;
Coordinated animations&lt;br&gt;
Feels premium and polished&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real impact&lt;/strong&gt; (WellMe AI):&lt;/p&gt;

&lt;p&gt;User engagement: 34% more users enabled dark mode&lt;br&gt;
App Store reviews: "Love the smooth theme switch!"&lt;br&gt;
Session time: 12% increase in evening usage&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Setup (Without Animation)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install Dependencies&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;npm install react-native-reanimated
npm install react-native-mmkv

# iOS
cd ios &amp;amp;&amp;amp; pod install &amp;amp;&amp;amp; cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why these:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;react-native-reanimated&lt;/code&gt;: Smooth 60 FPS animations&lt;br&gt;
&lt;code&gt;react-native-mmkv&lt;/code&gt;: Instant theme persistence (no AsyncStorage lag)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Create Theme Configuration&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;// theme.js
export const lightTheme = {
  background: '#FFFFFF',
  text: '#000000',
  card: '#F5F5F5',
  border: '#E0E0E0',
  primary: '#007AFF',
  secondary: '#8E8E93',
  success: '#34C759',
  error: '#FF3B30',
  shadow: 'rgba(0, 0, 0, 0.1)',
};

export const darkTheme = {
  background: '#000000',
  text: '#FFFFFF',
  card: '#1C1C1E',
  border: '#38383A',
  primary: '#0A84FF',
  secondary: '#98989D',
  success: '#30D158',
  error: '#FF453A',
  shadow: 'rgba(255, 255, 255, 0.1)',
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why these colors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Match iOS Human Interface Guidelines&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proper contrast ratios (WCAG AA compliant)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tested on 1000+ users in production&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Theme Context Provider&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;// ThemeContext.js
import React, { createContext, useState, useContext, useEffect } from 'react';
import { MMKV } from 'react-native-mmkv';
import { lightTheme, darkTheme } from './theme';

const storage = new MMKV();
const ThemeContext = createContext();

export const ThemeProvider = ({ children }) =&amp;gt; {
  const [isDark, setIsDark] = useState(() =&amp;gt; {
    // Load saved theme instantly (MMKV is synchronous!)
    const saved = storage.getString('theme');
    return saved === 'dark';
  });

  const theme = isDark ? darkTheme : lightTheme;

  const toggleTheme = () =&amp;gt; {
    const newTheme = !isDark;
    setIsDark(newTheme);
    storage.set('theme', newTheme ? 'dark' : 'light');
  };

  return (
    &amp;lt;ThemeContext.Provider value={{ theme, isDark, toggleTheme }}&amp;gt;
      {children}
    &amp;lt;/ThemeContext.Provider&amp;gt;
  );
};

export const useTheme = () =&amp;gt; useContext(ThemeContext);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why MMKV:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant load (no async/await delay)&lt;/li&gt;
&lt;li&gt;Theme appears immediately on app launch&lt;/li&gt;
&lt;li&gt;No flash of wrong theme&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Animated Theme Switching (iPhone Style)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Magic: Animated Values&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;// ThemeContext.js with Animation
import React, { createContext, useState, useContext, useEffect } from 'react';
import { MMKV } from 'react-native-mmkv';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withTiming,
  interpolateColor,
} from 'react-native-reanimated';
import { lightTheme, darkTheme } from './theme';

const storage = new MMKV();
const ThemeContext = createContext();

export const ThemeProvider = ({ children }) =&amp;gt; {
  const [isDark, setIsDark] = useState(() =&amp;gt; {
    const saved = storage.getString('theme');
    return saved === 'dark';
  });

  // Animated value: 0 = light, 1 = dark
  const progress = useSharedValue(isDark ? 1 : 0);

  const toggleTheme = () =&amp;gt; {
    const newTheme = !isDark;
    setIsDark(newTheme);
    storage.set('theme', newTheme ? 'dark' : 'light');

    // Animate transition
    progress.value = withTiming(newTheme ? 1 : 0, {
      duration: 300, // iPhone-like timing
    });
  };

  // Interpolate colors
  const animatedTheme = {
    background: interpolateColor(
      progress.value,
      [0, 1],
      [lightTheme.background, darkTheme.background]
    ),
    text: interpolateColor(
      progress.value,
      [0, 1],
      [lightTheme.text, darkTheme.text]
    ),
    card: interpolateColor(
      progress.value,
      [0, 1],
      [lightTheme.card, darkTheme.card]
    ),
    // ... other colors
  };

  const theme = isDark ? darkTheme : lightTheme;

  return (
    &amp;lt;ThemeContext.Provider value={{ theme, isDark, toggleTheme, progress, animatedTheme }}&amp;gt;
      {children}
    &amp;lt;/ThemeContext.Provider&amp;gt;
  );
};

export const useTheme = () =&amp;gt; useContext(ThemeContext);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Animated Components&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;// AnimatedScreen.js
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
import { useTheme } from './ThemeContext';

const AnimatedScreen = () =&amp;gt; {
  const { animatedTheme, progress } = useTheme();

  const animatedContainerStyle = useAnimatedStyle(() =&amp;gt; ({
    backgroundColor: animatedTheme.background,
  }));

  const animatedTextStyle = useAnimatedStyle(() =&amp;gt; ({
    color: animatedTheme.text,
  }));

  return (
    &amp;lt;Animated.View style={[styles.container, animatedContainerStyle]}&amp;gt;
      &amp;lt;Animated.Text style={[styles.text, animatedTextStyle]}&amp;gt;
        Smooth Theme Transition!
      &amp;lt;/Animated.Text&amp;gt;
    &amp;lt;/Animated.View&amp;gt;
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    fontSize: 24,
    fontWeight: 'bold',
  },
});

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

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;iPhone-Style Toggle Button *&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ThemeToggle.js
import React from 'react';
import { TouchableOpacity, StyleSheet } from 'react-native';
import Animated, {
  useAnimatedStyle,
  interpolate,
  interpolateColor,
} from 'react-native-reanimated';
import { useTheme } from './ThemeContext';

const ThemeToggle = () =&amp;gt; {
  const { isDark, toggleTheme, progress } = useTheme();

  // Animate toggle background
  const animatedToggleStyle = useAnimatedStyle(() =&amp;gt; ({
    backgroundColor: interpolateColor(
      progress.value,
      [0, 1],
      ['#E5E5EA', '#39393D'] // iOS toggle colors
    ),
  }));

  // Animate moon/sun icon position
  const animatedIconStyle = useAnimatedStyle(() =&amp;gt; ({
    transform: [
      {
        translateX: interpolate(progress.value, [0, 1], [0, 24]),
      },
    ],
    opacity: interpolate(progress.value, [0, 0.5, 1], [1, 0, 1]),
  }));

  // Rotate icon smoothly
  const animatedRotation = useAnimatedStyle(() =&amp;gt; ({
    transform: [
      {
        rotate: `${interpolate(progress.value, [0, 1], [0, 180])}deg`,
      },
    ],
  }));

  return (
    &amp;lt;TouchableOpacity onPress={toggleTheme} activeOpacity={0.8}&amp;gt;
      &amp;lt;Animated.View style={[styles.toggle, animatedToggleStyle]}&amp;gt;
        &amp;lt;Animated.View style={[styles.iconContainer, animatedIconStyle, animatedRotation]}&amp;gt;
          &amp;lt;Text style={styles.icon}&amp;gt;{isDark ? '🌙' : '☀️'}&amp;lt;/Text&amp;gt;
        &amp;lt;/Animated.View&amp;gt;
      &amp;lt;/Animated.View&amp;gt;
    &amp;lt;/TouchableOpacity&amp;gt;
  );
};

const styles = StyleSheet.create({
  toggle: {
    width: 60,
    height: 32,
    borderRadius: 16,
    padding: 2,
    justifyContent: 'center',
  },
  iconContainer: {
    width: 28,
    height: 28,
    borderRadius: 14,
    backgroundColor: '#FFFFFF',
    justifyContent: 'center',
    alignItems: 'center',
  },
  icon: {
    fontSize: 16,
  },
});

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Matches iOS toggle design exactly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Smooth icon transition with rotation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;60 FPS animation guaranteed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced: Circular Reveal Animation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;iPhone-style expanding circle transition:&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;// CircularRevealTransition.js
import React, { useEffect } from 'react';
import { StyleSheet, Dimensions } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withTiming,
} from 'react-native-reanimated';
import { useTheme } from './ThemeContext';

const { width, height } = Dimensions.get('window');
const DIAGONAL = Math.sqrt(width * width + height * height);

const CircularReveal = () =&amp;gt; {
  const { isDark, theme } = useTheme();
  const scale = useSharedValue(0);

  useEffect(() =&amp;gt; {
    // Animate circle from center
    scale.value = withTiming(isDark ? 1 : 0, {
      duration: 400,
    });
  }, [isDark]);

  const animatedStyle = useAnimatedStyle(() =&amp;gt; ({
    transform: [{ scale: scale.value * 2 }],
    backgroundColor: theme.background,
  }));

  return (
    &amp;lt;Animated.View 
      style={[styles.circle, animatedStyle]}
      pointerEvents="none"
    /&amp;gt;
  );
};

const styles = StyleSheet.create({
  circle: {
    position: 'absolute',
    width: DIAGONAL,
    height: DIAGONAL,
    borderRadius: DIAGONAL / 2,
    top: height / 2 - DIAGONAL / 2,
    left: width / 2 - DIAGONAL / 2,
  },
});

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&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;View style={{ flex: 1 }}&amp;gt;
  &amp;lt;AnimatedScreen /&amp;gt;
  &amp;lt;CircularReveal /&amp;gt;
  &amp;lt;ThemeToggle /&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  System Theme Detection
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Respect user's system preference:&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;// ThemeContext.js with System Detection
import { useColorScheme } from 'react-native';

export const ThemeProvider = ({ children }) =&amp;gt; {
  const systemTheme = useColorScheme(); // 'light' | 'dark' | null

  const [themeMode, setThemeMode] = useState(() =&amp;gt; {
    const saved = storage.getString('theme_mode');
    return saved || 'system'; // 'light' | 'dark' | 'system'
  });

  const isDark = themeMode === 'system' 
    ? systemTheme === 'dark'
    : themeMode === 'dark';

  const setTheme = (mode) =&amp;gt; {
    setThemeMode(mode);
    storage.set('theme_mode', mode);
  };

  return (
    &amp;lt;ThemeContext.Provider value={{ theme, isDark, themeMode, setTheme }}&amp;gt;
      {children}
    &amp;lt;/ThemeContext.Provider&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Settings UI:&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;const ThemeSettings = () =&amp;gt; {
  const { themeMode, setTheme } = useTheme();

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;TouchableOpacity onPress={() =&amp;gt; setTheme('light')}&amp;gt;
        &amp;lt;Text&amp;gt;☀️ Light {themeMode === 'light' &amp;amp;&amp;amp; '✓'}&amp;lt;/Text&amp;gt;
      &amp;lt;/TouchableOpacity&amp;gt;

      &amp;lt;TouchableOpacity onPress={() =&amp;gt; setTheme('dark')}&amp;gt;
        &amp;lt;Text&amp;gt;🌙 Dark {themeMode === 'dark' &amp;amp;&amp;amp; '✓'}&amp;lt;/Text&amp;gt;
      &amp;lt;/TouchableOpacity&amp;gt;

      &amp;lt;TouchableOpacity onPress={() =&amp;gt; setTheme('system')}&amp;gt;
        &amp;lt;Text&amp;gt;📱 System {themeMode === 'system' &amp;amp;&amp;amp; '✓'}&amp;lt;/Text&amp;gt;
      &amp;lt;/TouchableOpacity&amp;gt;
    &amp;lt;/View&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete Production Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// App.js
import React from 'react';
import { StatusBar } from 'react-native';
import { ThemeProvider, useTheme } from './ThemeContext';
import HomeScreen from './screens/HomeScreen';

const AppContent = () =&amp;gt; {
  const { isDark } = useTheme();

  return (
    &amp;lt;&amp;gt;
      &amp;lt;StatusBar
        barStyle={isDark ? 'light-content' : 'dark-content'}
        animated
      /&amp;gt;
      &amp;lt;HomeScreen /&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

const App = () =&amp;gt; {
  return (
    &amp;lt;ThemeProvider&amp;gt;
      &amp;lt;AppContent /&amp;gt;
    &amp;lt;/ThemeProvider&amp;gt;
  );
};

export default App;
&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;// HomeScreen.js
import React from 'react';
import { View, Text, StyleSheet, ScrollView } from 'react-native';
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
import { useTheme } from '../ThemeContext';
import ThemeToggle from '../components/ThemeToggle';

const HomeScreen = () =&amp;gt; {
  const { theme, animatedTheme, progress } = useTheme();

  const animatedContainerStyle = useAnimatedStyle(() =&amp;gt; ({
    backgroundColor: animatedTheme.background,
  }));

  const animatedTextStyle = useAnimatedStyle(() =&amp;gt; ({
    color: animatedTheme.text,
  }));

  const animatedCardStyle = useAnimatedStyle(() =&amp;gt; ({
    backgroundColor: animatedTheme.card,
  }));

  return (
    &amp;lt;Animated.View style={[styles.container, animatedContainerStyle]}&amp;gt;
      &amp;lt;View style={styles.header}&amp;gt;
        &amp;lt;Animated.Text style={[styles.title, animatedTextStyle]}&amp;gt;
          Dark Mode Demo
        &amp;lt;/Animated.Text&amp;gt;
        &amp;lt;ThemeToggle /&amp;gt;
      &amp;lt;/View&amp;gt;

      &amp;lt;ScrollView style={styles.content}&amp;gt;
        &amp;lt;Animated.View style={[styles.card, animatedCardStyle]}&amp;gt;
          &amp;lt;Animated.Text style={[styles.cardTitle, animatedTextStyle]}&amp;gt;
            Smooth Animations
          &amp;lt;/Animated.Text&amp;gt;
          &amp;lt;Animated.Text style={[styles.cardText, animatedTextStyle]}&amp;gt;
            Every color transitions smoothly at 60 FPS
          &amp;lt;/Animated.Text&amp;gt;
        &amp;lt;/Animated.View&amp;gt;

        &amp;lt;Animated.View style={[styles.card, animatedCardStyle]}&amp;gt;
          &amp;lt;Animated.Text style={[styles.cardTitle, animatedTextStyle]}&amp;gt;
            Instant Persistence
          &amp;lt;/Animated.Text&amp;gt;
          &amp;lt;Animated.Text style={[styles.cardText, animatedTextStyle]}&amp;gt;
            Theme saved instantly with MMKV
          &amp;lt;/Animated.Text&amp;gt;
        &amp;lt;/Animated.View&amp;gt;

        &amp;lt;Animated.View style={[styles.card, animatedCardStyle]}&amp;gt;
          &amp;lt;Animated.Text style={[styles.cardTitle, animatedTextStyle]}&amp;gt;
            iPhone-Style Polish
          &amp;lt;/Animated.Text&amp;gt;
          &amp;lt;Animated.Text style={[styles.cardText, animatedTextStyle]}&amp;gt;
            Matches iOS design guidelines perfectly
          &amp;lt;/Animated.Text&amp;gt;
        &amp;lt;/Animated.View&amp;gt;
      &amp;lt;/ScrollView&amp;gt;
    &amp;lt;/Animated.View&amp;gt;
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: 20,
    paddingTop: 60,
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
  },
  content: {
    flex: 1,
    padding: 20,
  },
  card: {
    padding: 20,
    borderRadius: 12,
    marginBottom: 16,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginBottom: 8,
  },
  cardText: {
    fontSize: 14,
    opacity: 0.7,
  },
});

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Optimization
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Memoize Theme Objects&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;const theme = useMemo(() =&amp;gt; {
  return isDark ? darkTheme : lightTheme;
}, [isDark]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Use Native Driver (Where Possible)&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;progress.value = withTiming(newTheme ? 1 : 0, {
  duration: 300,
  useNativeDriver: true, // Runs on UI thread
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Avoid Re-renders&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;// ❌ BAD - Re-renders entire tree
const { theme, isDark, toggleTheme } = useTheme();

// ✅ GOOD - Only subscribe to what you need
const isDark = useTheme().isDark;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Not Persisting Theme&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;// ❌ BAD - Theme resets on app restart
const [isDark, setIsDark] = useState(false);

// ✅ GOOD - Theme persists
const [isDark, setIsDark] = useState(() =&amp;gt; {
  return storage.getString('theme') === 'dark';
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Flash of Wrong Theme&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;// ❌ BAD - Async load causes flash
const [isDark, setIsDark] = useState(false);

useEffect(() =&amp;gt; {
  AsyncStorage.getItem('theme').then(theme =&amp;gt; {
    setIsDark(theme === 'dark'); // Flash!
  });
}, []);

// ✅ GOOD - Synchronous MMKV
const [isDark, setIsDark] = useState(() =&amp;gt; {
  return storage.getString('theme') === 'dark'; // Instant!
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Forgetting StatusBar&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;// ✅ Always animate StatusBar too
&amp;lt;StatusBar
  barStyle={isDark ? 'light-content' : 'dark-content'}
  animated // Smooth transition
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced: Multiple Theme Support
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// themes.js
export const themes = {
  light: {
    background: '#FFFFFF',
    text: '#000000',
    // ...
  },
  dark: {
    background: '#000000',
    text: '#FFFFFF',
    // ...
  },
  sunset: {
    background: '#FF6B6B',
    text: '#FFFFFF',
    // ...
  },
  ocean: {
    background: '#0077BE',
    text: '#FFFFFF',
    // ...
  },
};

// ThemeContext.js
const [currentTheme, setCurrentTheme] = useState(() =&amp;gt; {
  return storage.getString('theme') || 'light';
});

const theme = themes[currentTheme];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Stop doing instant theme switches in 2025.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After implementing animated dark mode in different apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;40-60% higher dark mode adoption&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Positive mentions in reviews&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better user engagement&lt;/strong&gt; (especially evening usage)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Premium feel&lt;/strong&gt; that users appreciate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The difference:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant switch: Feels like web app&lt;/li&gt;
&lt;li&gt;Animated switch: Feels like native iOS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementation time:&lt;/strong&gt; 20 mints&lt;br&gt;&lt;br&gt;
&lt;strong&gt;User perception:&lt;/strong&gt; "This app is polished"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your users won't say "nice animation."&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;They'll say "this app feels premium."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's what matters.&lt;/p&gt;

</description>
      <category>themes</category>
      <category>reactnative</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I created rn-animation-kit — a simple, powerful animation library that makes adding beautiful animations as easy as wrapping a component.</title>
      <dc:creator>noman akram</dc:creator>
      <pubDate>Fri, 19 Dec 2025 07:26:36 +0000</pubDate>
      <link>https://dev.to/noman_akram_6c329a67f88ca/i-created-rn-animation-kit-a-simple-powerful-animation-library-that-makes-adding-beautiful-2bh4</link>
      <guid>https://dev.to/noman_akram_6c329a67f88ca/i-created-rn-animation-kit-a-simple-powerful-animation-library-that-makes-adding-beautiful-2bh4</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/noman_akram_6c329a67f88ca" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3670121%2Ffa3f7b23-568e-4243-8164-de24875e2e1d.jpg" alt="noman_akram_6c329a67f88ca"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/noman_akram_6c329a67f88ca/introducing-rn-animation-kit-the-easiest-way-to-add-beautiful-animations-to-your-react-native-app-4ho4" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Introducing rn-animation-kit: The Easiest Way to Add Beautiful Animations to Your React Native App&lt;/h2&gt;
      &lt;h3&gt;noman akram ・ Dec 19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#reactnative&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#android&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>programming</category>
      <category>javascript</category>
      <category>reactnative</category>
      <category>android</category>
    </item>
    <item>
      <title>Introducing rn-animation-kit: The Easiest Way to Add Beautiful Animations to Your React Native App</title>
      <dc:creator>noman akram</dc:creator>
      <pubDate>Fri, 19 Dec 2025 07:24:53 +0000</pubDate>
      <link>https://dev.to/noman_akram_6c329a67f88ca/introducing-rn-animation-kit-the-easiest-way-to-add-beautiful-animations-to-your-react-native-app-4ho4</link>
      <guid>https://dev.to/noman_akram_6c329a67f88ca/introducing-rn-animation-kit-the-easiest-way-to-add-beautiful-animations-to-your-react-native-app-4ho4</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel9dyjca4wvo9dit5zmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel9dyjca4wvo9dit5zmh.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why animations matter (and why they’re usually a pain)
&lt;/h2&gt;

&lt;p&gt;We’ve all been there. You’re building a beautiful React Native app, everything looks great, but it feels… lifeless. You know animations would make it pop, but the thought of implementing them makes you want to curl up in a ball.&lt;/p&gt;

&lt;p&gt;You’ve tried react-native-animated. You’ve wrestled with timing functions. You’ve spent hours debugging why your component won’t fade in properly. And after all that work, you still don’t have the smooth, professional animations your app deserves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing rn-animation-kit
&lt;/h2&gt;

&lt;p&gt;After building dozens of React Native apps and writing the same animation code over and over, I decided enough was enough. I created rn-animation-kit — a simple, powerful animation library that makes adding beautiful animations as easy as wrapping a component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add rn-animation-kit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. No complex setup. No configuration files. Just install and start animating.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Philosophy: Wrap and Animate
&lt;/h2&gt;

&lt;p&gt;The core idea behind &lt;strong&gt;rn-animation-kit&lt;/strong&gt; is dead simple: wrap your component, get an animation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { FadeIn } from 'rn-animation-kit';

function MyComponent() {
  return (
    &amp;lt;FadeIn direction="top"&amp;gt;
      &amp;lt;Text&amp;gt;I fade in from the top!&amp;lt;/Text&amp;gt;
    &amp;lt;/FadeIn&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s literally all you need. No hooks, no refs, no state management. Just wrap and go.&lt;/p&gt;

&lt;h2&gt;
  
  
  7 Animation Types, Infinite Possibilities
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. FadeIn — The Classic&lt;/strong&gt;&lt;br&gt;
Perfect for page transitions and subtle element reveals.&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;FadeIn direction="top" distance={100} delay={200}&amp;gt;
  &amp;lt;WelcomeMessage /&amp;gt;
&amp;lt;/FadeIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supports 8 directions: top, bottom, left, right, and all four diagonals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. SlideIn — Smooth Transitions&lt;/strong&gt;&lt;br&gt;
Great for modals, side menus, and navigation transitions.&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;SlideIn direction="left"&amp;gt;
  &amp;lt;Sidebar /&amp;gt;
&amp;lt;/SlideIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component slides in from completely off-screen, creating that native app feel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. ScaleIn — Pop with Personality&lt;/strong&gt;&lt;br&gt;
Add depth and emphasis to important elements.&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;ScaleIn initialScale={0.5}&amp;gt;
  &amp;lt;CallToAction /&amp;gt;
&amp;lt;/ScaleIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. RotateIn — Catch the Eye&lt;/strong&gt; &lt;br&gt;
Perfect for loading indicators, refresh actions, or playful UI elements.&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;RotateIn rotation={360} direction="clockwise"&amp;gt;
  &amp;lt;RefreshIcon /&amp;gt;
&amp;lt;/RotateIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. BounceIn — Elastic Energy&lt;/strong&gt;&lt;br&gt;
Create that satisfying bounce effect for notifications and alerts.&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;BounceIn direction="bottom" bounceHeight={100}&amp;gt;
  &amp;lt;Notification message="New message!" /&amp;gt;
&amp;lt;/BounceIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uses realistic physics for that professional touch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. FlipIn — 3D Depth&lt;/strong&gt;&lt;br&gt;
Add dimension with card flips and reveals.&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;FlipIn axis="y"&amp;gt;
  &amp;lt;Card /&amp;gt;
&amp;lt;/FlipIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7. ZoomIn — Attention Grabber&lt;/strong&gt;&lt;br&gt;
Perfect for modals and important announcements.&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;ZoomIn initialScale={0} overshoot={1.1}&amp;gt;
  &amp;lt;Modal /&amp;gt;
&amp;lt;/ZoomIn&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Composition: Where the Magic Happens
&lt;/h2&gt;

&lt;p&gt;Individual animations are great, but the real power comes from composition. That’s where Sequence and Parallel come in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sequence: Stagger Like a Pro&lt;/strong&gt;&lt;br&gt;
Create that smooth, cascading effect for lists&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;Sequence stagger={100}&amp;gt;
  {products.map((product) =&amp;gt; (
    &amp;lt;FadeIn key={product.id} direction="left"&amp;gt;
      &amp;lt;ProductCard product={product} /&amp;gt;
    &amp;lt;/FadeIn&amp;gt;
  ))}
&amp;lt;/Sequence&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each card fades in 100ms after the previous one. Simple, elegant, professional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallel: Orchestrate Complex Animations&lt;/strong&gt;&lt;br&gt;
Animate multiple elements simultaneously:&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;Parallel delay={200}&amp;gt;
  &amp;lt;FadeIn direction="top"&amp;gt;
    &amp;lt;Header /&amp;gt;
  &amp;lt;/FadeIn&amp;gt;
  &amp;lt;SlideIn direction="left"&amp;gt;
    &amp;lt;Sidebar /&amp;gt;
  &amp;lt;/SlideIn&amp;gt;
  &amp;lt;ScaleIn&amp;gt;
    &amp;lt;MainContent /&amp;gt;
  &amp;lt;/ScaleIn&amp;gt;
&amp;lt;/Parallel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three components animate at once, creating a rich, coordinated entrance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Examples
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Onboarding Screen&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;function OnboardingScreen() {
  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;FadeIn direction="top" distance={100}&amp;gt;
        &amp;lt;Logo /&amp;gt;
      &amp;lt;/FadeIn&amp;gt;

      &amp;lt;Sequence stagger={150} delay={300}&amp;gt;
        &amp;lt;FadeIn direction="left"&amp;gt;
          &amp;lt;Title&amp;gt;Welcome to Our App&amp;lt;/Title&amp;gt;
        &amp;lt;/FadeIn&amp;gt;
        &amp;lt;FadeIn direction="right"&amp;gt;
          &amp;lt;Subtitle&amp;gt;Build amazing things&amp;lt;/Subtitle&amp;gt;
        &amp;lt;/FadeIn&amp;gt;
        &amp;lt;ScaleIn&amp;gt;
          &amp;lt;Button title="Get Started" /&amp;gt;
        &amp;lt;/ScaleIn&amp;gt;
      &amp;lt;/Sequence&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2: Animated List&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;function ProductList({ products }) {
  return (
    &amp;lt;Sequence stagger={75}&amp;gt;
      {products.map((product, index) =&amp;gt; (
        &amp;lt;FadeIn 
          key={product.id} 
          direction="top-left"
          distance={50}
        &amp;gt;
          &amp;lt;ProductCard product={product} /&amp;gt;
        &amp;lt;/FadeIn&amp;gt;
      ))}
    &amp;lt;/Sequence&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That smooth, staggered reveal that makes your app feel premium? Five lines of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 3: Modal with Backdrop&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;function AnimatedModal({ visible, onClose }) {
  if (!visible) return null;

  return (
    &amp;lt;&amp;gt;
      &amp;lt;FadeIn&amp;gt;
        &amp;lt;Backdrop onPress={onClose} /&amp;gt;
      &amp;lt;/FadeIn&amp;gt;

      &amp;lt;ZoomIn initialScale={0.8} overshoot={1.05}&amp;gt;
        &amp;lt;View style={styles.modal}&amp;gt;
          &amp;lt;Sequence stagger={50}&amp;gt;
            &amp;lt;FadeIn direction="top"&amp;gt;
              &amp;lt;ModalHeader /&amp;gt;
            &amp;lt;/FadeIn&amp;gt;
            &amp;lt;FadeIn direction="left"&amp;gt;
              &amp;lt;ModalContent /&amp;gt;
            &amp;lt;/FadeIn&amp;gt;
            &amp;lt;ScaleIn&amp;gt;
              &amp;lt;ModalActions /&amp;gt;
            &amp;lt;/ScaleIn&amp;gt;
          &amp;lt;/Sequence&amp;gt;
        &amp;lt;/View&amp;gt;
      &amp;lt;/ZoomIn&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A complete, production-ready animated modal with backdrop fade and content animation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 4: Notification Toast&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;function Toast({ visible, message }) {
  return (
    &amp;lt;BounceIn 
      animate={visible}
      direction="top"
      bounceHeight={80}
      onAnimationComplete={() =&amp;gt; {
        setTimeout(() =&amp;gt; setVisible(false), 2000);
      }}
    &amp;gt;
      &amp;lt;View style={styles.toast}&amp;gt;
        &amp;lt;Text&amp;gt;{message}&amp;lt;/Text&amp;gt;
      &amp;lt;/View&amp;gt;
    &amp;lt;/BounceIn&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bouncy toast notifications with automatic dismissal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built on Solid Foundations
&lt;/h2&gt;

&lt;p&gt;Under the hood, &lt;strong&gt;rn-animation-kit&lt;/strong&gt; uses react-native-reanimated — the industry standard for React Native animations. This means:&lt;/p&gt;

&lt;p&gt;60 FPS performance — Animations run on the native thread&lt;br&gt;
Cross-platform — Works identically on iOS and Android&lt;br&gt;
Battle-tested — Built on technology used by thousands of production apps&lt;br&gt;
Future-proof — Leverages the React Native team’s recommended animation library&lt;/p&gt;

&lt;p&gt;You get all the power of Reanimated without the complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Makes It Fast?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Native thread animations — Runs at 60 FPS even when JS thread is busy&lt;/li&gt;
&lt;li&gt;Minimal re-renders — Uses useSharedValue to avoid component re-renders&lt;/li&gt;
&lt;li&gt;Optimized spring physics — Pre-configured spring settings for smooth motion&lt;/li&gt;
&lt;li&gt;No state management overhead — Animations are self-contained&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Who Is This For?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You should use rn-animation-kit if:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ You want professional animations without the learning curve&lt;br&gt;
✅ You’re tired of writing boilerplate animation code&lt;br&gt;
✅ You need consistent animations across your entire app&lt;br&gt;
✅ You value developer experience and clean code&lt;br&gt;
✅ You want TypeScript support out of the box&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You might not need it if:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ You need highly custom, complex animation choreography&lt;br&gt;
❌ You’re already a Reanimated expert with custom solutions&lt;br&gt;
❌ Your app has zero animations (though you should reconsider!)&lt;/p&gt;

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

&lt;p&gt;Building great mobile apps is hard enough. Animations shouldn’t make it harder. With rn-animation-kit, you get professional, performant animations with minimal code. Spend less time fighting with animation APIs and more time building features your users love.&lt;/p&gt;

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

&lt;p&gt;📦 NPM: npmjs.com/package/rn-animation-kit&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>reactnative</category>
      <category>android</category>
    </item>
  </channel>
</rss>
