<?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: Gais Dev</title>
    <description>The latest articles on DEV Community by Gais Dev (@gaisdav).</description>
    <link>https://dev.to/gaisdav</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%2F2903334%2F6ec61620-25c5-4e82-b31e-eb775c368966.png</url>
      <title>DEV Community: Gais Dev</title>
      <link>https://dev.to/gaisdav</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gaisdav"/>
    <language>en</language>
    <item>
      <title>Do You Really Need a Backend? Supabase as a Solution for MVPs and Startups</title>
      <dc:creator>Gais Dev</dc:creator>
      <pubDate>Fri, 18 Apr 2025 10:52:34 +0000</pubDate>
      <link>https://dev.to/gaisdav/do-you-really-need-a-backend-supabase-as-a-solution-for-mvps-and-startups-2dl5</link>
      <guid>https://dev.to/gaisdav/do-you-really-need-a-backend-supabase-as-a-solution-for-mvps-and-startups-2dl5</guid>
      <description>&lt;p&gt;When you're working on an MVP or testing a startup idea, building a full-fledged backend is often overkill. It takes time, effort, and resources you might not have — especially if you're working solo or in a small team.&lt;/p&gt;

&lt;p&gt;That’s where Supabase comes in. It's an open-source alternative to Firebase that lets you move fast, build quickly, and focus on your product instead of infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Why Supabase?
&lt;/h2&gt;

&lt;p&gt;Supabase gives you a backend instantly — with authentication, a PostgreSQL database, file storage, and real-time subscriptions — all out of the box. And the best part? You can manage everything through an intuitive dashboard and integrate it directly with your frontend.&lt;/p&gt;

&lt;p&gt;It’s a great option for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MVPs&lt;/li&gt;
&lt;li&gt;Hackathons&lt;/li&gt;
&lt;li&gt;Side projects&lt;/li&gt;
&lt;li&gt;Early-stage startups&lt;/li&gt;
&lt;li&gt;Products with uncertain future scope&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚙️ Easy Setup, Fast Integration
&lt;/h2&gt;

&lt;p&gt;Supabase is incredibly easy to get started with. You can create a project in minutes and connect it to your frontend via the official &lt;a href="https://supabase.com/docs/reference/javascript/installing" rel="noopener noreferrer"&gt;JavaScript SDK&lt;/a&gt;.&lt;br&gt;
Here’s an example of connecting Supabase to a React app:&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 @supabase/supabase-js
&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;// src/supabaseClient.ts
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'https://your-project-id.supabase.co'
const supabaseAnonKey = 'your-anon-key'

export const supabase = createClient(supabaseUrl, supabaseAnonKey)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can query your database from any component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Example: fetch all users
useEffect(() =&amp;gt; {
  const getUsers = async () =&amp;gt; {
    const { data, error } = await supabase.from('users').select('*')
    if (error) console.error(error)
    else console.log(data)
  }

  getUsers()
}, [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📦 What You Get with the Free Tier
&lt;/h2&gt;

&lt;p&gt;Supabase offers a generous free plan, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 projects&lt;/li&gt;
&lt;li&gt;500MB database space per project&lt;/li&gt;
&lt;li&gt;1GB file storage&lt;/li&gt;
&lt;li&gt;50MB bandwidth&lt;/li&gt;
&lt;li&gt;100K monthly edge function invocations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most MVPs, that’s more than enough. You can always scale later as your project grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 PostgreSQL Inside = Easy Migration Later
&lt;/h2&gt;

&lt;p&gt;Supabase runs on PostgreSQL, so if you ever outgrow the platform or want to move to a custom backend, you’re not locked in. You can easily migrate your database, use familiar SQL tools, and integrate with traditional backends later.&lt;/p&gt;

&lt;p&gt;This flexibility is a huge win over Firebase or proprietary systems that don’t give you control over your data.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Supabase vs Firebase: What’s the Difference?
&lt;/h2&gt;

&lt;p&gt;Both Supabase and Firebase aim to help developers move fast without managing infrastructure. However, they take different approaches and suit different needs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Supabase&lt;/th&gt;
&lt;th&gt;Firebase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;PostgreSQL (SQL)&lt;/td&gt;
&lt;td&gt;Firestore / Realtime DB (NoSQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Source&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Queries&lt;/td&gt;
&lt;td&gt;SQL (powerful and flexible)&lt;/td&gt;
&lt;td&gt;NoSQL query language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Realtime Support&lt;/td&gt;
&lt;td&gt;✅ Realtime via subscriptions&lt;/td&gt;
&lt;td&gt;✅ Realtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Storage&lt;/td&gt;
&lt;td&gt;✅ Included&lt;/td&gt;
&lt;td&gt;✅ Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge Functions&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;✅ Cloud Functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosting&lt;/td&gt;
&lt;td&gt;✅ Possible&lt;/td&gt;
&lt;td&gt;❌ Not officially supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Migration Flexibility&lt;/td&gt;
&lt;td&gt;✅ Easy with PostgreSQL&lt;/td&gt;
&lt;td&gt;⚠️ More complex with NoSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Supabase might be a better fit if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You prefer SQL and relational data&lt;/li&gt;
&lt;li&gt;You want more control over your database&lt;/li&gt;
&lt;li&gt;You plan to migrate to a custom backend later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Firebase shines in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Realtime-heavy mobile apps&lt;/li&gt;
&lt;li&gt;Fully managed NoSQL infrastructure&lt;/li&gt;
&lt;li&gt;Seamless integration with Google Cloud tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both tools are powerful — it depends on what you’re building and your team's preferences.&lt;/p&gt;

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

&lt;p&gt;If you’re building an MVP, testing a hypothesis, or launching a side project — you might not need a custom backend at all. Supabase provides a modern, open-source stack that helps you move faster and build smarter, without compromising flexibility in the long term.&lt;/p&gt;

&lt;p&gt;Try it out, build your app, and validate your idea. If it works — you can scale from there. If not — you didn’t waste months building infrastructure you never needed.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;https://supabase.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>startup</category>
      <category>backendless</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>How to Prevent Theme Flash in a React: Instant Dark Mode Switching</title>
      <dc:creator>Gais Dev</dc:creator>
      <pubDate>Fri, 04 Apr 2025 12:19:12 +0000</pubDate>
      <link>https://dev.to/gaisdav/how-to-prevent-theme-flash-in-a-react-instant-dark-mode-switching-o20</link>
      <guid>https://dev.to/gaisdav/how-to-prevent-theme-flash-in-a-react-instant-dark-mode-switching-o20</guid>
      <description>&lt;p&gt;When implementing dark mode in a React application, a common problem arises: when the app loads, the initial HTML is displayed with the default light theme before JavaScript executes and applies the user's saved theme. This results in a "flash" effect where the page briefly appears in the wrong theme before correcting itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Problem
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;When a web application loads, the browser first renders &lt;code&gt;index.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The JavaScript file responsible for React and theming loads afterward.&lt;/li&gt;
&lt;li&gt;If the theme is stored in &lt;code&gt;localStorage&lt;/code&gt;, React applies it only after hydration.&lt;/li&gt;
&lt;li&gt;This leads to a noticeable flicker, especially for users who prefer dark mode.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Solution: Applying the Theme Before React Loads
&lt;/h2&gt;

&lt;p&gt;To eliminate this issue, we can apply the saved theme immediately using a small inline script in &lt;code&gt;index.html&lt;/code&gt;. This script runs before the HTML is rendered, ensuring that the correct theme is applied instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;Add the following script inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of &lt;code&gt;index.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;THEME_ATTRIBUTE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-theme&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;GET_THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDeviceDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-color-scheme: dark)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;THEME_ATTRIBUTE_KEY&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="nx"&gt;isDeviceDark&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;themeValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;themeValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meta[name='theme-color']&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;themeValue&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#1c1c1e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;THEME_ATTRIBUTE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;themeValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GET_THEME&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nc"&gt;SET_THEME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This script runs immediately when &lt;code&gt;index.html&lt;/code&gt; loads, before React initializes.&lt;/li&gt;
&lt;li&gt;It reads the user's theme preference from &lt;code&gt;localStorage&lt;/code&gt; or detects the system preference.&lt;/li&gt;
&lt;li&gt;It applies the theme by setting the &lt;code&gt;data-theme&lt;/code&gt; attribute (light or dark) on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element.&lt;/li&gt;
&lt;li&gt;It also sets the &lt;code&gt;theme-color&lt;/code&gt; meta tag for a more cohesive experience on mobile devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Update &lt;code&gt;meta[name='theme-color']&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;meta name="theme-color"&amp;gt;&lt;/code&gt; tag is especially useful for mobile users. It controls the color of the browser’s UI elements, such as the address bar in Chrome on Android. Updating it dynamically ensures that the UI blends seamlessly with the selected theme.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Approach and Its Downsides
&lt;/h2&gt;

&lt;p&gt;A quick way to prevent the theme flicker is to add a simple inline script that applies the stored theme immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that the theme is applied before React loads, avoiding the white flash.&lt;/p&gt;

&lt;p&gt;However, there's a downside to this approach: we now have duplicate logic.&lt;br&gt;
Since this script only runs on page load, we still need a separate function in React to switch themes dynamically when the user toggles between dark and light mode.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Keeping All Logic in One Place Is Better
&lt;/h3&gt;

&lt;p&gt;In our approach, we define reusable functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The script in index.html ensures the theme is set instantly.&lt;/li&gt;
&lt;li&gt;The same functions are used inside React components.&lt;/li&gt;
&lt;li&gt;No need for duplicate logic—theme switching is handled in one place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the implementation more &lt;strong&gt;maintainable&lt;/strong&gt; and &lt;strong&gt;scalable&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using TypeScript for Better Type Safety
&lt;/h2&gt;

&lt;p&gt;If you're using TypeScript in your React project, you can declare the global functions and constants in a separate &lt;code&gt;.d.ts&lt;/code&gt; file to ensure type safety:&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="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_THEME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;themeValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_THEME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;THEME_ATTRIBUTE_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to use these functions in your React components with full TypeScript support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GET_THEME&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;handleThemeToggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;SET_THEME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, TypeScript will catch any incorrect usage of these global functions, making your code more robust and maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential Drawbacks and Considerations
&lt;/h2&gt;

&lt;p&gt;While this solution is effective, there are a few potential downsides to keep in mind:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Global Function Names Could Cause Conflicts
&lt;/h3&gt;

&lt;p&gt;Declaring &lt;code&gt;SET_THEME&lt;/code&gt; and &lt;code&gt;GET_THEME&lt;/code&gt; globally may lead to conflicts in larger projects with multiple scripts. To avoid this, you can encapsulate them within an object attached to &lt;code&gt;window&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;themeUtils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SET_THEME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GET_THEME&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in React, you can access them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;themeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GET_THEME&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;themeUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SET_THEME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&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;h3&gt;
  
  
  2. &lt;code&gt;localStorage&lt;/code&gt; May Not Always Be Available
&lt;/h3&gt;

&lt;p&gt;In some cases, such as when browsing in private mode on certain browsers, &lt;code&gt;localStorage&lt;/code&gt; may be restricted. To handle this, wrap &lt;code&gt;localStorage&lt;/code&gt; calls in &lt;code&gt;try-catch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safeLocalStorageGet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&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;null&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;Then update the theme retrieval function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDeviceDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(prefers-color-scheme: dark)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;safeLocalStorageGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;THEME_ATTRIBUTE_KEY&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="nx"&gt;isDeviceDark&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Hardcoded &lt;code&gt;light&lt;/code&gt; and &lt;code&gt;dark&lt;/code&gt; values
&lt;/h3&gt;

&lt;p&gt;If your application requires additional themes beyond just "light" and "dark," you’ll need a more flexible approach. One option is to store an array of available themes and validate the stored value before applying it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AVAILABLE_THEMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;solarized&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;GET_THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savedTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;THEME_ATTRIBUTE_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;AVAILABLE_THEMES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;savedTheme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;savedTheme&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;themeValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AVAILABLE_THEMES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;themeValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;/// code&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By applying the theme instantly in &lt;code&gt;index.html&lt;/code&gt;, we avoid the unwanted flash of the wrong theme during initial load. This simple yet effective technique significantly improves the user experience in React applications with theme switching.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, the method provided above might not work for all scenarios. However, I aimed to address the most common case that you might encounter, and this solution is generally sufficient for React applications with theme switching. Although it is slightly compromising, it strikes a good balance between simplicity and functionality for many typical use cases.&lt;/p&gt;

&lt;p&gt;To help you make an informed decision, I have highlighted some potential pitfalls and edge cases. If you encounter specific problems or need further details, feel free to reach out, and I can expand the article to cover more specific cases and solutions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>typescript</category>
      <category>darkmode</category>
    </item>
  </channel>
</rss>
