<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ localstorage - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ localstorage - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:20:53 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/localstorage/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Add Local Storage to Your Blazor Apps with Blazored.LocalStorage ]]>
                </title>
                <description>
                    <![CDATA[ By FADAHUNSI SEYI SAMUEL One critical feature of modern web applications is their ability to store and retrieve data on the client side. This is where local storage comes into play.  In this article, we'll explore how to leverage the power of the Bla... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-local-storage-in-blazor-apps/</link>
                <guid isPermaLink="false">66d45edd230dff01669057fb</guid>
                
                    <category>
                        <![CDATA[ Blazor ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ .NET ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 29 Jul 2024 13:55:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/pexels-pixabay-236698.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By FADAHUNSI SEYI SAMUEL</p>
<p>One critical feature of modern web applications is their ability to store and retrieve data on the <a target="_blank" href="https://www.cloudflare.com/learning/serverless/glossary/client-side-vs-server-side/">client side</a>. This is where <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage">local storage</a> comes into play. </p>
<p>In this article, we'll explore how to leverage the power of the <a target="_blank" href="https://www.nuget.org/packages/Blazored.LocalStorage">Blazored LocalStorage NuGet package</a> to seamlessly integrate <code>local storage</code> capabilities into your Blazor applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-understanding-local-storage">Understanding Local Storage</a></li>
<li><a class="post-section-overview" href="#heading-introducing-blazoredlocalstorage">Introducing Blazored.LocalStorage</a></li>
<li><a class="post-section-overview" href="#heading-advantages-of-using-blazoredlocalstorage-in-blazor-applications">Advantages of Using Blazored.LocalStorage in Blazor Applications</a></li>
<li><a class="post-section-overview" href="#heading-how-to-install-blazoredlocalstorage">How to Install Blazored.LocalStorage</a></li>
<li><a class="post-section-overview" href="#heading-install-using-the-nuget-package-manager">Install Using Nuget Package Manager</a></li>
<li><a class="post-section-overview" href="#heading-install-using-the-net-cli">Install Using the .NET CLI</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-blazoredlocalstorage">How to Use Blazored.LocalStorage</a></li>
<li><a class="post-section-overview" href="#heading-advanced-features-and-techniques">Advanced Features and Techniques</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Make sure you have the necessary tools installed on your computer before continuing with this guide:</p>
<ul>
<li>To build and update <a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-8.0">Blazor</a> projects, you'll need <a target="_blank" href="https://visualstudio.microsoft.com/downloads/">Visual Studio</a>, a feature-rich Integrated Development Environment (IDE) which you can download from the official <a target="_blank" href="https://visualstudio.microsoft.com/downloads/">Microsoft website here</a>.</li>
<li>The <a target="_blank" href="https://dotnet.microsoft.com/en-us/download">.NET SDK</a> (Software Development Kit) has everything you need to create and execute <a target="_blank" href="https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet">.NET</a> apps, and it's required for Blazor projects. Make sure your computer has the <code>.NET SDK</code> installed.</li>
<li>Basic knowledge of <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/">C#</a> and Blazor.</li>
</ul>
<p>With these installed, will be ready to follow along.</p>
<h2 id="heading-understanding-local-storage">Understanding Local Storage</h2>
<p>Local storage is a <code>key-value</code> pair storage mechanism supported by modern web browsers. It provides a simple way to store data persistently on the user's device. Unlike <code>session storage</code>, which is cleared when the browser session ends, <code>local storage</code> remains intact even after closing the browser window.</p>
<p><a target="_blank" href="https://www.nuget.org/packages/Blazored.LocalStorage">Blazored.LocalStorage</a> is a powerful library that simplifies working with the browser's local storage <code>API</code> (Application Programming Interface) within Blazor applications. It provides a convenient <code>API</code> for storing, retrieving, and managing data in local storage.</p>
<p>By abstracting away the complexities of directly interacting with the <code>localStorage</code> API, this package provides an intuitive and type-safe interface. It lets you focus on building feature-rich Blazor applications without worrying about the underlying storage mechanisms.</p>
<h2 id="heading-introducing-blazoredlocalstorage">Introducing Blazored.LocalStorage</h2>
<p><code>Blazored.LocalStorage</code> is an open-source library designed to provide easy and accessible local storage management in Blazor applications. This library is compatible with both <a target="_blank" href="https://www.pragimtech.com/blog/blazor-webAssembly/what-is-blazor-webassembly/">Blazor WebAssembly</a> and <a target="_blank" href="https://www.c-sharpcorner.com/article/understanding-server-side-blazor/">Blazor Server</a> projects. This makes it a versatile choice for Blazor developers looking to enhance their applications with persistent, client-side storage capabilities.</p>
<p>At its core, <code>Blazored.LocalStorage</code> facilitates the storage and retrieval of data in the browser's local storage, allowing data to persist across browser sessions. </p>
<p>This is particularly useful for storing user preferences, application state, and other data that needs to persist between page reloads without the need for a database or backend storage solution.</p>
<h3 id="heading-advantages-of-using-blazoredlocalstorage-in-blazor-applications">Advantages of Using Blazored.LocalStorage in Blazor Applications</h3>
<p>The inclusion of <code>Blazored.LocalStorage</code> in Blazor applications comes with a host of benefits, including:</p>
<ul>
<li>Simplified State Management: By leveraging local storage, applications can maintain state more effectively across user sessions, enhancing the user experience.</li>
<li>Performance Improvements: Storing data locally reduces the need for frequent server requests, leading to faster application performance and reduced server load.</li>
<li>Enhanced User Experience: Preferences and application states can be preserved, meaning users do not need to reconfigure settings or lose their place in the application upon returning.</li>
<li>Easy Integration: The <code>API</code> provided by <code>Blazored.LocalStorage</code> is designed to be intuitive and straightforward, ensuring that developers can integrate local storage capabilities into their applications with minimal effort.</li>
<li>Cross-Session Persistence: Unlike session storage or in-memory data storage, local storage ensures that data persists across browser sessions and tab closures, providing a more consistent user experience.</li>
</ul>
<h2 id="heading-how-to-install-blazoredlocalstorage">How to Install Blazored.LocalStorage</h2>
<p>Integrating <code>Blazored.LocalStorage</code> into your Blazor project is straightforward, with support for installation via the <code>NuGet Package Manager</code> or the <code>.NET CLI</code> (Command Line Interpreter).</p>
<h3 id="heading-install-using-the-nuget-package-manager">Install Using the NuGet Package Manager</h3>
<p>Using <code>Visual Studio</code>, you can easily add <code>Blazored.LocalStorage</code> by following these steps:</p>
<ul>
<li>Open your Blazor project in Visual Studio.</li>
<li>Navigate to the “Solution Explorer”, right-click on "Dependencies", and select “Manage NuGet Packages”.</li>
</ul>
<p><img src="https://hackmd.io/_uploads/S1ckU8ll0.png" alt="Annotation 2024-04-07 181852" width="600" height="400" loading="lazy"></p>
<ul>
<li>In the NuGet Package Manager, click on the “Browse” tab and search for “Blazored.LocalStorage”.</li>
</ul>
<p><img src="https://hackmd.io/_uploads/HkBjUUxxC.png" alt="2024-04-07_18-22-49" width="600" height="400" loading="lazy"></p>
<ul>
<li>Find the package in the list, select it, and click “Install”.</li>
</ul>
<p>Visual Studio will handle the rest, adding the package to your project along with any dependencies.</p>
<h3 id="heading-install-using-the-net-cli">Install Using the .NET CLI</h3>
<p>For those who prefer using the command line or are working within a development environment other than Visual Studio, the <code>.NET CLI</code> provides a simple method to add <code>Blazored.LocalStorage</code>:</p>
<pre><code class="lang-csharp">dotnet <span class="hljs-keyword">add</span> package Blazored.LocalStorage
</code></pre>
<p>Run the command above in your <code>terminal</code> or <code>command prompt</code> from the root directory of your Blazor project. The CLI will download and install <code>Blazored.LocalStorage</code> along with any necessary dependencies.</p>
<h2 id="heading-how-to-use-blazoredlocalstorage">How to Use Blazored.LocalStorage</h2>
<p>Let's dive into some basic examples of using Blazored.LocalStorage in a Blazor application.</p>
<h3 id="heading-how-to-register-blazoredlocalstorage-in-your-blazor-application">How to Register Blazored.LocalStorage in your Blazor Application</h3>
<p>We will register<code>Blazored.LocalStorage</code> into the root of the application, so that it will be available to use everywhere in the application.</p>
<p>In the <code>program.cs</code> file, which is our root file, we will register the <code>Blazored.LocalStorage</code> service by doing the following:</p>
<pre><code class="lang-csharp">builder.Services.AddBlazoredLocalStorage();
</code></pre>
<p>The code snippet above registers the <code>Blazored.LocalStorage</code> into the application. For this to work, make sure you add the code below to the top of the <code>program.cs</code> file:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Blazored.LocalStorage;
</code></pre>
<p>The code snippet above makes sure that the <code>Blazored.LocalStorage</code> is being imported to be used in the file. If you've added everything correctly, your <code>program.cs</code> file should look like this:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> BlazorApp9.Components;
<span class="hljs-keyword">using</span> Blazored.LocalStorage;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorApp9</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>)</span>
    {
        <span class="hljs-keyword">var</span> builder = WebApplication.CreateBuilder(args);

        builder.Services.AddRazorComponents()
            .AddInteractiveServerComponents();

        builder.Services.AddBlazoredLocalStorage();

        <span class="hljs-keyword">var</span> app = builder.Build();

        <span class="hljs-keyword">if</span> (!app.Environment.IsDevelopment())
        {
            app.UseExceptionHandler(<span class="hljs-string">"/Error"</span>);
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseStaticFiles();
        app.UseAntiforgery();

        app.MapRazorComponents&lt;App&gt;()
            .AddInteractiveServerRenderMode();

        app.Run();
    }
}
</code></pre>
<p>The above is the full code that should be in your <code>program.cs</code> file. With this, you can now use <code>Blazored.LocalStorage</code> anywhere in the application to store and receive data.</p>
<h3 id="heading-how-to-store-and-retrieve-data-in-blazoredlocalstorage">How to Store and Retrieve Data in Blazored.LocalStorage</h3>
<p>Let's consider a simple scenario where we want to store and retrieve a piece of data using local storage. We'll create a Blazor page with two buttons: one to store data and another to retrieve it.</p>
<pre><code class="lang-csharp">@page <span class="hljs-string">"/"</span>

@inject Blazored.LocalStorage.ILocalStorageService localStorage
@rendermode RenderMode.InteractiveServer

&lt;h3&gt;Local Storage Example&lt;/h3&gt;

&lt;input @bind-<span class="hljs-keyword">value</span>=<span class="hljs-string">"@inputData"</span> /&gt;

&lt;button @onclick=<span class="hljs-string">"StoreData"</span>&gt;Store Data&lt;/button&gt;
&lt;button @onclick=<span class="hljs-string">"RetrieveData"</span>&gt;Retrieve Data&lt;/button&gt;

&lt;p&gt;The retrieved data <span class="hljs-keyword">from</span> the LocalStorage: @storedData &lt;/p&gt;

@code {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> dataKey = <span class="hljs-string">"localStorageKey"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? storedData;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? inputData;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">StoreData</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span>(!<span class="hljs-keyword">string</span>.IsNullOrWhiteSpace(inputData))
        {
            <span class="hljs-keyword">await</span> localStorage.SetItemAsync(dataKey, inputData);
            inputData = <span class="hljs-string">""</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">OnAfterRenderAsync</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> firstRender</span>)</span>
    {
        <span class="hljs-keyword">if</span> (firstRender)
        {
            <span class="hljs-keyword">await</span> RetrieveData();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">RetrieveData</span>(<span class="hljs-params"></span>)</span>
    {
        storedData = <span class="hljs-keyword">await</span> localStorage.GetItemAsync&lt;<span class="hljs-keyword">string</span>&gt;(dataKey);
    }
}
</code></pre>
<p>In the code snippet above, the <code>@inject Blazored.LocalStorage.ILocalStorageService localStorage</code> injects the local storage service to interact with the browser's local storage. The <code>@rendermode RenderMode.InteractiveServer</code> specifies that the page should be rendered as an interactive server-side component. Without the interactive server, the page will not be interactive.</p>
<p>The input field binds to <code>inputData</code> using the <code>@bind-value</code> attribute, allowing users to enter data they wish to store. The <code>dataKey</code> is a constant variable used to store and retrieve data from local storage. The <code>storedData</code> and <code>inputData</code> variables are used to hold the data to be stored and retrieved.</p>
<p>The <code>StoreData</code> method checks to see if <code>inputData</code> is not empty. If not, it stores it in local storage using <code>dataKey</code>, and clears the input field. </p>
<p><code>OnAfterRenderAsync</code> is triggered after the component's first render. It retrieves data from local storage to ensure that data persists even after the page is reloaded. </p>
<p><code>RetrieveData</code> retrieves data from local storage and assigns it to <code>storedData</code> for display.</p>
<p><img src="https://hackmd.io/_uploads/H1DGRAL-0.gif" alt="2024-04-15_00-52-31 (1) (1) (1) (1)" width="600" height="400" loading="lazy"></p>
<p>The video above explains how to store and retrieve data stored in localstorage on the client-side.</p>
<h2 id="heading-advanced-features-and-techniques">Advanced Features and Techniques</h2>
<p>In this section, we'll talk about how you can set an expiration date on your data, and how the stored data can be encrypted and decrypted for security.</p>
<h3 id="heading-how-to-manage-the-expiration-of-stored-data">How to Manage the Expiration of Stored Data</h3>
<p>To manage the expiration of your stored data, you will create a helper class that stores data along with an expiration timestamp. Create a file called <code>StorageItem.cs</code> which will contain the code below:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">StorageItem</span>&lt;<span class="hljs-title">T</span>&gt;
{
    <span class="hljs-keyword">public</span> required T Data { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> DateTime Expiry { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>The code snippet above is a <code>StorageItem&lt;T&gt;</code> class, which is a generic class that can hold data of any type <code>T</code> and an expiry date <code>DateTime</code>. The Data property is required to be set when an instance of <code>StorageItem</code> is created or initialized, ensuring that it always has a valid value. The <code>Expiry</code> property represents the expiration date of the stored data.</p>
<p>Next, you'll create a file which will be a class that contains methods to set and get from the LocalStorage, with an expiration time. Create a file called <code>LocalStorageHelper.cs</code>:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Blazored.LocalStorage;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorApp9.Components.Helpers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">LocalStorageHelper</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">SetItemAsyncWithExpiry</span>&lt;<span class="hljs-title">T</span>&gt;(<span class="hljs-params">ILocalStorageService localStorageService, <span class="hljs-keyword">string</span> key, TimeSpan expiry, T data</span>)</span>
    {
        StorageItem&lt;T&gt; storageItem = <span class="hljs-keyword">new</span> StorageItem&lt;T&gt;
        {
            Data = data,
            Expiry = DateTime.UtcNow.Add(expiry)
        };

        <span class="hljs-keyword">await</span> localStorageService.SetItemAsync(key, storageItem);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> <span class="hljs-title">Task</span>&lt;<span class="hljs-title">T</span>?&gt; <span class="hljs-title">GetItemAsyncWithExpiry</span>&lt;<span class="hljs-title">T</span>&gt;(<span class="hljs-params">ILocalStorageService localStorageService, <span class="hljs-keyword">string</span> key</span>)</span>
    {
         <span class="hljs-keyword">var</span> storageItem = <span class="hljs-keyword">await</span> localStorageService.GetItemAsync&lt;StorageItem&lt;T&gt;&gt;(key);

        <span class="hljs-keyword">if</span>(storageItem <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">default</span>;
        }

        <span class="hljs-keyword">if</span> (storageItem.Expiry &lt; DateTime.UtcNow)
        {
            <span class="hljs-keyword">await</span> localStorageService.RemoveItemAsync(key);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">default</span>;
        }
        <span class="hljs-keyword">return</span> storageItem.Data;
    }
}
</code></pre>
<p>In the code above, you can see the necessary <code>using</code> directive for the <code>Blazored.LocalStorage</code> library. It provides easy access to the browser's local storage from Blazor applications. </p>
<p>This is followed by the declaration of the namespace <code>BlazorApp9.Components.Helpers</code>. This organizes the code and indicates that this helper is part of a specific component's helpers within the Blazor application.</p>
<p>Next, the <code>LocalStorageHelper</code> class is defined as a <code>static</code> class. A static class is one that cannot be instantiated and can only contain static members (using non static methods or properties will not be accepted). </p>
<p>Within the <code>LocalStorageHelper</code> class, two <code>static</code> asynchronous methods are defined: <code>SetItemAsyncWithExpiry</code> and <code>GetItemAsyncWithExpiry</code>.</p>
<p>The <code>SetItemAsyncWithExpiry</code> method is responsible for storing an item in the local storage with an associated expiry time. It accepts an <code>ILocalStorageService</code> instance for interacting with local storage, a <code>key</code> <code>string</code> to identify the stored item, a <code>TimeSpan</code> value representing the expiry duration, and the actual data to be stored. </p>
<p>Inside the method, a <code>StorageItem&lt;T&gt;</code> object is created, where <code>T</code> is the type of data being stored. This object includes the data and the expiry time, which is calculated by adding the specified <code>TimeSpan</code> to the current <a target="_blank" href="https://www.space.com/what-is-utc.html">UTC time</a>. </p>
<p>This <code>StorageItem</code> object is then serialized and saved in local storage under the given key using the <code>SetItemAsync</code> method of <code>ILocalStorageService</code>.</p>
<p>The <code>GetItemAsyncWithExpiry</code> method is responsible for retrieving an item from local storage and checking if it has expired. It also accepts an <code>ILocalStorageService</code> instance and a <code>key</code> <code>string</code>. </p>
<p>This method attempts to retrieve the stored <code>StorageItem&lt;T&gt;</code> object using the <code>key</code>. If the retrieved item is <code>null</code>, it returns the default value for the type <code>T</code> (typically <code>null</code> for reference types and zero or equivalent for value types). </p>
<p>If the item is found but its expiry time is earlier than the current UTC time, it means the item has expired. In this case, the item is removed from the local storage using the <code>RemoveItemAsync</code> method of <code>ILocalStorageService</code>, and the method returns the default value for <code>T</code>. If the item is valid and has not expired, the method returns the stored data.</p>
<h3 id="heading-how-to-implement-encryption-and-decryption">How to Implement Encryption and Decryption</h3>
<p>In this section, we will explore a utility file that provides encryption and decryption functionalities for a Blazor application. </p>
<p>The <code>EncryptionHelper.cs</code> class includes methods for encrypting and decrypting strings, as well as methods for serializing objects to <a target="_blank" href="https://www.w3schools.com/whatis/whatis_json.asp">JSON (Javascript Object Notation)</a> and then encrypting them. This ensures that sensitive data can be securely stored and transmitted. </p>
<p>Let’s dive into the code to understand how these methods work and how you can use them. Add the following code for this file:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Security.Cryptography;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> System.Text.Json;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorApp9.Components.Helpers</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">EncryptionHelper</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">string</span> EncryptionKey = <span class="hljs-string">"your-encryption-key"</span>;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] <span class="hljs-title">GetKeyBytes</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> key</span>)</span>
    {

        <span class="hljs-keyword">byte</span>[] keyBytes = Encoding.UTF8.GetBytes(key);
        Array.Resize(<span class="hljs-keyword">ref</span> keyBytes, <span class="hljs-number">32</span>);
        <span class="hljs-keyword">return</span> keyBytes;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span> <span class="hljs-title">Encrypt</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> plainText</span>)</span>
    {
        <span class="hljs-keyword">byte</span>[] iv = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">16</span>];
        <span class="hljs-keyword">byte</span>[] array;

        <span class="hljs-keyword">using</span> (Aes aes = Aes.Create())
        {
            aes.Key = GetKeyBytes(EncryptionKey);
            aes.IV = iv;

            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

            <span class="hljs-keyword">using</span> (MemoryStream memoryStream = <span class="hljs-keyword">new</span> MemoryStream())
            {
                <span class="hljs-keyword">using</span> (CryptoStream cryptoStream = <span class="hljs-keyword">new</span> CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    <span class="hljs-keyword">using</span> (StreamWriter streamWriter = <span class="hljs-keyword">new</span> StreamWriter((Stream)cryptoStream))
                    {
                        streamWriter.Write(plainText);
                    }

                    array = memoryStream.ToArray();
                }
            }
        }

        <span class="hljs-keyword">return</span> Convert.ToBase64String(array);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span> <span class="hljs-title">Decrypt</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> cipherText</span>)</span>
    {
        <span class="hljs-keyword">byte</span>[] iv = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">16</span>];
        <span class="hljs-keyword">byte</span>[] buffer = Convert.FromBase64String(cipherText);

        <span class="hljs-keyword">using</span> (Aes aes = Aes.Create())
        {
            aes.Key = GetKeyBytes(EncryptionKey);
            aes.IV = iv;

            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

            <span class="hljs-keyword">using</span> (MemoryStream memoryStream = <span class="hljs-keyword">new</span> MemoryStream(buffer))
            {
                <span class="hljs-keyword">using</span> (CryptoStream cryptoStream = <span class="hljs-keyword">new</span> CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
                {
                    <span class="hljs-keyword">using</span> (StreamReader streamReader = <span class="hljs-keyword">new</span> StreamReader((Stream)cryptoStream))
                    {
                        <span class="hljs-keyword">return</span> streamReader.ReadToEnd();
                    }
                }
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span> <span class="hljs-title">SerializeAndEncrypt</span>&lt;<span class="hljs-title">T</span>&gt;(<span class="hljs-params">T data</span>)</span>
    {
        <span class="hljs-keyword">var</span> jsonString = JsonSerializer.Serialize(data);
        <span class="hljs-keyword">return</span> Encrypt(jsonString);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> T <span class="hljs-title">DecryptAndDeserialize</span>&lt;<span class="hljs-title">T</span>&gt;(<span class="hljs-params"><span class="hljs-keyword">string</span> cipherText</span>)</span>
    {
        <span class="hljs-keyword">var</span> json = Decrypt(cipherText);
        <span class="hljs-keyword">return</span> JsonSerializer.Deserialize&lt;T&gt;(json);
    }
}
</code></pre>
<p>The <code>EncryptionHelper</code> class is a static helper class designed for encrypting and decrypting data. This is particularly useful for securing sensitive information in a Blazor application. </p>
<p>The class above defines a <code>static</code> <code>readonly</code> field <code>EncryptionKey</code> which holds the encryption key. This key is crucial for both the encryption and decryption processes. It's important to use a strong and securely stored key.</p>
<p>The <code>GetKeyBytes</code> method converts the string key into a byte array and ensures its length is 32 bytes. This is because <a target="_blank" href="https://www.techtarget.com/searchsecurity/definition/Advanced-Encryption-Standard">the AES encryption</a> algorithm requires a 256-bit key, which is 32 bytes long.</p>
<p>The <code>Encrypt</code> method encrypts a <code>plaintext</code> string using <code>AES</code> encryption. It first creates an initialization vector (IV) of 16 bytes, which is required by the <code>AES</code> algorithm. The method then sets up an <code>AES</code> object with the encryption key and IV, and uses a <code>CryptoStream</code> to write the encrypted data to a memory stream. This encrypted data is then converted to a <code>base64</code> string for easy storage and transmission.</p>
<p>The <code>Decrypt</code> method performs the reverse operation. It converts a <code>base64</code> string back to a byte array, sets up the <code>AES</code> object with the same key and IV, and uses a <code>CryptoStream</code> to read the decrypted data from the memory stream. The result is the original plaintext string.</p>
<p>The <code>EncryptionHelper</code> class provides two methods for handling complex data structures: <code>SerializeAndEncrypt</code> and <code>DecryptAndDeserialize</code>. The <code>SerializeAndEncrypt</code> method first serializes an object to a <code>JSON</code> string using <code>JsonSerializer.Serialize</code>, and then encrypts this <code>JSON</code> string using the <code>Encrypt</code> method. This allows complex objects to be securely stored in an encrypted format.</p>
<p>The <code>DecryptAndDeserialize</code> method decrypts an encrypted <code>JSON</code> string back into its original form and then deserializes it into an object of type T using <code>JsonSerializer.Deserialize</code>. This combination of decryption and deserialization ensures that complex data can be securely retrieved and used within the application.</p>
<h3 id="heading-how-to-connect-the-expiration-and-encryption-to-the-user-interface">How to Connect the Expiration and Encryption to the User Interface</h3>
<p>Now we'll walk through a Blazor component (<code>Home.razor</code>) that allows users to store and retrieve encrypted data in the browser's local storage. This ensures that sensitive information is protected and automatically expires when no longer needed. </p>
<p>This approach combines the ease of local storage with the security of encryption, providing a robust solution for managing user data in web applications. Let's dive into the code to see how it works.</p>
<pre><code class="lang-csharp"> @page <span class="hljs-string">"/"</span>
@using BlazorApp9.Components.Helpers

@inject Blazored.LocalStorage.ILocalStorageService localStorage
@rendermode RenderMode.InteractiveServer

&lt;h3&gt;Local Storage Example&lt;/h3&gt;

&lt;input @bind-<span class="hljs-keyword">value</span>=<span class="hljs-string">"@inputData"</span> /&gt;

&lt;button @onclick=<span class="hljs-string">"StoreData"</span>&gt;Store Data&lt;/button&gt;
&lt;button @onclick=<span class="hljs-string">"RetrieveData"</span>&gt;Retrieve Data&lt;/button&gt;

&lt;p&gt;The retrieved data <span class="hljs-keyword">from</span> the LocalStorage: @storedData &lt;/p&gt;

@code {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> dataKey = <span class="hljs-string">"localStorageKey"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? storedData;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span>? inputData;

    <span class="hljs-keyword">bool</span> isDataLoaded = <span class="hljs-literal">false</span>;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">StoreData</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">string</span>.IsNullOrWhiteSpace(inputData))
        {
            <span class="hljs-keyword">string</span> encryptData = EncryptionHelper.SerializeAndEncrypt(inputData);
            <span class="hljs-keyword">await</span> LocalStorageHelper.SetItemAsyncWithExpiry(localStorage, dataKey, TimeSpan.FromMinutes(<span class="hljs-number">30</span>), encryptData);
            inputData = <span class="hljs-string">""</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">OnAfterRenderAsync</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> firstRender</span>)</span>
    {
        <span class="hljs-keyword">if</span> (firstRender &amp;&amp; !isDataLoaded)
        {
            <span class="hljs-keyword">await</span> RetrieveData();
            isDataLoaded = <span class="hljs-literal">true</span>;
            StateHasChanged();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">RetrieveData</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">string</span> encryptData = <span class="hljs-keyword">await</span> LocalStorageHelper.GetItemAsyncWithExpiry&lt;<span class="hljs-keyword">string</span>&gt;(localStorage, dataKey);
        storedData = encryptData != <span class="hljs-literal">null</span> ? EncryptionHelper.DecryptAndDeserialize&lt;<span class="hljs-keyword">string</span>&gt;(encryptData) : <span class="hljs-string">"Data not found or expired."</span>;
    }
}
</code></pre>
<p>In the code above, the <code>StoreData</code> method checks if <code>inputData</code> is valid, encrypts it using <code>EncryptionHelper.SerializeAndEncrypt</code>, and stores it in local storage with a thirty-minute expiry using <code>LocalStorageHelper.SetItemAsyncWithExpiry</code>. The input field is then cleared.</p>
<p>The <code>OnAfterRenderAsync</code> method retrieves data from local storage after the component's initial render. This ensures previously stored data is loaded when the page first displays. It runs once, setting <code>isDataLoaded</code> to true and calling <code>StateHasChanged</code> to update the user interface (UI).</p>
<p>The <code>RetrieveData</code> method fetches data from local storage using <code>LocalStorageHelper.GetItemAsyncWithExpiry</code>. If the data is found and valid, it decrypts and deserializes it using <code>EncryptionHelper.DecryptAndDeserialize</code>. If not, it sets <code>storedData</code> to "<code>Data not found or expired.</code>"</p>
<p><img src="https://hackmd.io/_uploads/BJRDqJUNR.gif" alt="2024-05-30_11-18-37 (1) (2) (1)" width="600" height="400" loading="lazy"></p>
<p>The video above demonstrates how you can implement the concepts discussed in this guide in a web application.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p><code>Blazored.LocalStorage</code> offers a powerful and easy-to-use solution for managing user information in Blazor applications. Its integration brings numerous benefits, including enhanced state management, improved performance, and a better user experience.</p>
<p>After reading through this article and trying out the code for yourself, you should be able to incorporate local storage capabilities into any Blazor project. This will help you unlock the full potential of client-side storage in your web applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Store Data Locally in React Native Expo ]]>
                </title>
                <description>
                    <![CDATA[ React Native has grown in popularity as a mobile application development tool because of its ability to create cross-platform applications using familiar JavaScript and React principles.  When building mobile applications, one common requirement is t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-store-data-locally-in-react-native-expo/</link>
                <guid isPermaLink="false">66b9ee747bae781916c2d6dd</guid>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ John Caleb ]]>
                </dc:creator>
                <pubDate>Mon, 13 May 2024 11:42:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/local-storage-in--react-native-expo--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>React Native has grown in popularity as a mobile application development tool because of its ability to create cross-platform applications using familiar JavaScript and React principles. </p>
<p>When building mobile applications, one common requirement is the ability to save data locally on the device. This is when local storage comes into play. <a target="_blank" href="https://docs.expo.dev/versions/latest/sdk/async-storage/">Async Storage</a>, provided by React Native Expo, is a simple but powerful solution for saving data locally within your React Native Expo apps.</p>
<p>In this tutorial, we'll discuss the fundamentals of local storage, introduce Async Storage, and demonstrate how to properly integrate it into React Native Expo projects.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-what-is-local-storage">What is Local Storage?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-async-storage">What is Async Storage?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-get-started-with-async-storage">How to Get Started with Async Storage</a></li>
<li><a class="post-section-overview" href="#heading-understanding-async-storage-methods">Understanding Async Storage Methods</a></li>
<li><a class="post-section-overview" href="#heading-advanced-usage-and-best-practices">Advanced Usage and Best Practices</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Familiarity with React Native and JavaScript.</li>
<li>Node.js and npm (or yarn) installed.</li>
</ul>
<h2 id="heading-what-is-local-storage">What is Local Storage?</h2>
<p>Local storage is an essential component of mobile app development, allowing developers to store data on the user's device. Unlike other storage choices such as databases, Local Storage uses a straightforward key-value pair storage technique.</p>
<p>Developers can use it to save small quantities of data that remain stored even when they close the program or restart the device. This makes it excellent for storing user preferences, authentication tokens, and other important information.</p>
<p>Local storage is essential for boosting app speed because it eliminates the need to retrieve data from faraway servers regularly.</p>
<h2 id="heading-what-is-async-storage">What is Async Storage?</h2>
<p>Async Storage is a key-value storage system supplied by React Native Expo that allows you to manage local storage in mobile apps. It provides a simple key-value storage system that enables developers to store and retrieve data asynchronously. </p>
<p>Unlike synchronous storage methods, Async Storage allows you to save and retrieve data without interrupting the main thread, resulting in a more seamless user experience.</p>
<h2 id="heading-how-to-get-started-with-async-storage">How to Get Started with Async Storage</h2>
<p>To use Async Storage in your React Native Expo project, ensure that Expo is installed. If you haven't already set up a React Native Expo project, you can do so by installing Expo CLI:</p>
<pre><code class="lang-bash">$ npm install -g expo-cli
</code></pre>
<p>Create a new Expo project:</p>
<pre><code class="lang-bash">$ expo init MyProject
$ <span class="hljs-built_in">cd</span> MyProject
</code></pre>
<p>To add Async Storage to your project, run the following command:</p>
<pre><code class="lang-js">$ expo install @react-native-<span class="hljs-keyword">async</span>-storage/<span class="hljs-keyword">async</span>-storage
</code></pre>
<p>The <code>@react-native-async-storage/async-storage</code> is a community-maintained version of AsyncStorage. Once installed, you can then setup a file to handle the AsyncStorage methods such as <code>setItem()</code>, <code>updateItem()</code>, <code>deleteItem()</code>, and others. This file would be imported whenever you want to make a call to the local storage. </p>
<p>In this example, we'll create a folder named <code>utils</code> in the root path of our project and then create the <code>AsyncStorage.js</code> file to handle these methods:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/-4611C08C-3557-460A-A7CC-BFD754BD13F7-.png.jpg" alt="Async Storage File Structure " width="600" height="400" loading="lazy">
<em>Async Storage File Structure</em></p>
<p>Within the <code>AsyncStorage.js</code> file, you can define the AsyncStorage methods like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// utils/AsyncStorage.js</span>

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

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

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

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

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

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

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getAllItems = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> keys = <span class="hljs-keyword">await</span> AsyncStorage.getAllKeys();
    <span class="hljs-keyword">const</span> items = <span class="hljs-keyword">await</span> AsyncStorage.multiGet(keys);
    <span class="hljs-keyword">return</span> items.reduce(<span class="hljs-function">(<span class="hljs-params">accumulator, [key, value]</span>) =&gt;</span> {
      accumulator[key] = <span class="hljs-built_in">JSON</span>.parse(value);
      <span class="hljs-keyword">return</span> accumulator;
    }, {});
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error getting all items:'</span>, error);
    <span class="hljs-keyword">return</span> {};
  }
};
</code></pre>
<p>Moving forward, In the next section, we'll explain and break down the meaning of these AsyncStorage functions in the AsyncStorage.js file.</p>
<h2 id="heading-understanding-async-storage-methods">Understanding Async Storage Methods</h2>
<p>By separating AsyncStorage functions into their own file, you can conveniently manage and reuse them throughout your React Native Expo project. This modular approach improves code maintenance and readability.</p>
<p>In the previous section, we created the <code>AsyncStorage.js</code> file and added several functions. </p>
<p>In the following sections, we'll talk about these methods and how to use them effectively.</p>
<h3 id="heading-setitem"><code>setItem()</code></h3>
<p>This method is essential for storing data locally on the device. It allows developers to store key-value pairs in AsyncStorage, where the key serves as a unique identifier and the value represents the data to be stored.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.setItem(<span class="hljs-string">'username'</span>, <span class="hljs-string">'freeCodeCamp'</span>);
</code></pre>
<h3 id="heading-getitem"><code>getItem()</code></h3>
<p>The <code>getItem()</code> method returns the value associated with a given key from local storage. It sends a parameter/key, which is the unique identification of the data being requested. And it returns the value associated with the supplied key, or null if no value is discovered for the given key.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> username = <span class="hljs-keyword">await</span> AsyncStorage.getItem(<span class="hljs-string">'username'</span>);
</code></pre>
<p>In this scenario, the value for the key <code>username</code> is fetched from local storage. This obtained value, <code>freeCodeCamp</code>, is then placed in the variable username, making it available for further use across the application.</p>
<h3 id="heading-removeitem"><code>removeItem()</code></h3>
<p>This function deletes the object with the supplied key from local storage. It's useful when you want to remove a specific piece of data that's no longer required.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.removeItem(<span class="hljs-string">'username'</span>);
</code></pre>
<p>In this example, the object identified by the key <code>username</code> is removed from local storage.</p>
<h3 id="heading-mergeitem"><code>mergeItem()</code></h3>
<p>The <code>mergeItem()</code> method combines the value of an existing key with the value supplied as input. If the key do not exists, it works similarly to <code>setItem()</code>, creating a new key-value pair.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.mergeItem(<span class="hljs-string">'user'</span>, <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span> }));
</code></pre>
<h3 id="heading-clear"><code>clear()</code></h3>
<p>The <code>clear()</code> method deletes all items from local storage. It's useful when you wish to delete all local data, such as when you log out of a user or reset the application state.</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> AsyncStorage.clear();
</code></pre>
<h3 id="heading-getallkeys"><code>getAllKeys()</code></h3>
<p>The <code>getAllKeys()</code> function returns all keys kept in local storage. It's useful when you need to loop through all keys or conduct operations based on the keys in local storage.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> keys = <span class="hljs-keyword">await</span> AsyncStorage.getAllKeys();
</code></pre>
<h3 id="heading-multiget"><code>multiGet()</code></h3>
<p>The <code>multiGet()</code> function obtains several key-value pairs from local storage using an array of keys provided.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> AsyncStorage.multiGet([<span class="hljs-string">'username'</span>, <span class="hljs-string">'email'</span>]);
</code></pre>
<p>In this example, the values for the keys <code>username</code> and <code>email</code> are fetched from local storage.</p>
<h2 id="heading-advanced-usage-and-best-practices">Advanced Usage and Best Practices</h2>
<p>While AsyncStorage provides a straightforward interface for local storage, there are several best practices to consider:</p>
<ol>
<li><strong>Data Serialization</strong>: When storing complex data types such as objects or arrays, remember to serialize them into a string format using <code>JSON.stringify()</code> before storing and deserialize them using <code>JSON.parse()</code> when retrieving.</li>
<li><strong>Error Handling</strong>: Implement robust error handling to gracefully handle any failures that may occur during Async Storage operations.</li>
<li><strong>Security Considerations</strong>: Be mindful of the sensitivity of the data being stored locally and implement appropriate security measures such as encryption for sensitive information.</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, using local storage into your React Native Expo projects is essential for developing robust and responsive mobile applications. Async Storage simplifies the process of storing and retrieving data on the device, providing a consistent user experience and enabling offline functionalities. </p>
<p>By following the steps provided in this article, you can utilize Async Storage to improve your apps local storage functionality.</p>
<p>Remember, if you have any questions or just want to say hi, feel free to reach me on <a target="_blank" href="https://twitter.com/thejohncaleb">X(Twitter)</a> or my <a target="_blank" href="https://thejohncaleb.netlify.app/contact">website</a>. :)  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use LocalStorage in JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ In modern web development, having a way to persist data helps developers improve performance and create a better user experience. And using local storage is an effective way of persisting data in an application. In this article, you will learn what l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-local-storage-in-modern-applications/</link>
                <guid isPermaLink="false">66d45dedc7632f8bfbf1e417</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ storage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Benjamin Semah ]]>
                </dc:creator>
                <pubDate>Tue, 20 Feb 2024 21:37:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/JavaScript-localStorage-freeCodeCamp-Benjamin-Semah.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In modern web development, having a way to persist data helps developers improve performance and create a better user experience. And using local storage is an effective way of persisting data in an application.</p>
<p>In this article, you will learn what local storage is and how to use it in modern web applications. You will also learn the advantages of using local storage, as well as some of its limitations.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#what-is-local-storage">What is Local Storage?</a></p>
</li>
<li><p><a class="post-section-overview" href="#differences-between-local-storage-and-session-storage">Differences Between Local Storage and Session Storage</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-use-local-storage">How to Use Local Storage</a></p>
</li>
<li><p><a class="post-section-overview" href="#a-practical-example">A Practical Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-view-local-storage-in-devtools">How to View Local Storage in DevTools</a></p>
</li>
<li><p><a class="post-section-overview" href="#benefits-of-using-local-storage">Benefits of Using Local Storage</a></p>
</li>
<li><p><a class="post-section-overview" href="#limitations-of-using-local-storage">Limitations of Local Storage</a></p>
</li>
<li><p><a class="post-section-overview" href="#conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-local-storage">What is Local Storage?</h2>
<p>Local storage is a feature in web browsers that allows developers to save data in the user’s browser. It’s part of the web storage API, together with session storage.</p>
<p>Local storage works by accepting data in key-value pairs. It retains the data even when the user refreshes the page or closes the tab or browser.</p>
<h2 id="heading-differences-between-local-storage-and-session-storage">Differences Between Local Storage and Session Storage</h2>
<p>As I mentioned earlier, the web storage API in modern browsers provides two main features for data storage. These are local storage and session storage.</p>
<p>The key differences between the two are the lifespan of the stored data and their scope.</p>
<p>Data in local storage remains available even when the tab/browser is closed. But closing the tab/browser clears any data stored in session storage.</p>
<p>Also, data in local storage is accessible across multiple browser tabs and windows. On the other hand, data in session storage is only accessible within specific browser tabs and is not shared.</p>
<h2 id="heading-how-to-use-local-storage">How to Use Local Storage</h2>
<p>The local storage object provides different methods you can use to interact with it. With these methods, you can add, read, and delete data from local storage.</p>
<h3 id="heading-how-to-store-data-in-local-storage">How to Store Data in Local Storage</h3>
<p>To store data in local storage, you use the <code>setItem()</code> method. This method takes in two arguments, a key and a value.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">localStorage</span>.setItem(key, value)
</code></pre>
<p>If the key does not exist in local storage, the <code>setItem()</code> method will create a new key and assign the given value to it. But if a key with the same name exists in local storage, it will update the value of the key with the provided value.</p>
<h3 id="heading-how-to-read-data-from-local-storage">How to Read Data From Local Storage</h3>
<p>To retrieve and use data from local storage, you use the <code>getItem()</code> method. This method takes in a key as an argument.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">localStorage</span>.getItem(key)
</code></pre>
<p>If the given key exists in local storage, the method returns the value of that key. If it doesn’t, the method returns <code>null</code>.</p>
<h3 id="heading-how-to-store-and-read-complex-data-values-in-local-storage">How to Store and Read Complex Data Values in Local Storage</h3>
<p>Local storage can only store strings. This means if you need to store values like objects or arrays, you first need to get a string representation of the value. You do this using the <code>JSON.stringify()</code> method.</p>
<p>Example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> userObj = {
  username = <span class="hljs-string">"Maria"</span>,
  <span class="hljs-attr">email</span>: <span class="hljs-string">"maria@mail.com"</span>
}

<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'user'</span>, <span class="hljs-built_in">JSON</span>.stringify(userObj))
</code></pre>
<p>The <code>JSON.stringify()</code> method converts the <code>userObj</code> object into a string representation before sending it to local storage.</p>
<p>Now, when you want to retrieve the data back from local storage, you also need to change it from its string representation back to the original form. And you do that using the <code>JSON.parse()</code> method.</p>
<p>Example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> storedUserData = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'user'</span>)

<span class="hljs-keyword">if</span> (storedUserData) {
  <span class="hljs-keyword">const</span> userData = <span class="hljs-built_in">JSON</span>.parse(storedUserData)
  <span class="hljs-comment">// You can use userData here...</span>
} <span class="hljs-keyword">else</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User data not found in local storage'</span>)
}
</code></pre>
<p>In the example above, we first check if there is data for ‘user’ in local storage before using the <code>JSON.parse()</code> method. This is important because if it does not exist in local storage, <code>JSON.parse()</code> will be applied to a <code>null</code> value (which will result in an error).</p>
<h3 id="heading-how-to-delete-data-from-local-storage">How to Delete Data from Local Storage</h3>
<p>There are two methods available for deleting data from local storage. One is the <code>removeItem()</code> method and the other is the <code>clear()</code> method.</p>
<p>You use the <code>removeItem()</code> method when you want to delete a single item from local storage. The method takes in a key as an argument and deletes the corresponding key-value pair from local storage.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">localStorage</span>.removeItem(key)
</code></pre>
<p>But what if, instead of deleting a single key-value pair, you want to clear all data from the local storage? Well, local storage has a method for that - the <code>clear()</code> method.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">localStorage</span>.clear()
</code></pre>
<p>The <code>clear()</code> method deletes all key-value pairs in the local storage for the current domain.</p>
<h3 id="heading-how-to-get-the-name-of-a-key-in-local-storage">How to Get the Name of a Key in Local Storage</h3>
<p>If you want to get the name of a key at a particular index in local storage, you can use the <code>key()</code> method. It takes in a number as an argument and returns the name of the key at that specified index.</p>
<p>Example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">localStorage</span>.key(<span class="hljs-number">0</span>)
</code></pre>
<p>The example above will return the name of the key at index 0. If there is no key at the specified index, the method will return null.</p>
<h2 id="heading-a-practical-example">A Practical Example</h2>
<p>The following shows a practical demo of the difference between local storage and session storage.</p>
<p>In this example, we'll save the user's name in local storage and save the age in session storage.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- HTML --&gt;</span> 
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"userName"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"userAge"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter name here"</span>/&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"saveNameBtn"</span>&gt;</span>Save Name<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"age"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter age here"</span>/&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"saveAgeBtn"</span>&gt;</span>Save Age<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>The markup includes two header elements. One for <code>userName</code> and the other for <code>userAge</code>. It also includes two input elements for name and age. Each input has an associated button we'll use for saving the data.</p>
<p>Now, let's use the <code>querySelector</code> method to select the various elements.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> userNameText = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".userName"</span>)
<span class="hljs-keyword">const</span> userAgeText = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".userAge"</span>)

<span class="hljs-keyword">const</span> saveNameButton = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".saveNameBtn"</span>)
<span class="hljs-keyword">const</span> saveAgeButton = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".saveAgeBtn"</span>)
</code></pre>
<h3 id="heading-code-example-for-local-storage">Code Example for Local Storage</h3>
<pre><code class="lang-javascript">saveNameButton.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> userName = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".name"</span>).value
  userNameText.textContent = userName
  <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">"name"</span>, userName)
})
</code></pre>
<p>First, we get the value of the name input, set it as the <code>textContent</code> of <code>userNameText</code>. And then use the <code>setItem()</code> of local storage to save the <code>userName</code> value in local storage.</p>
<p>Next, let's see how we can get the name value from local storage when we need it.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayUserName</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> nameFromLocalStorage = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">"name"</span>)

  <span class="hljs-keyword">if</span> (nameFromLocalStorage) {
    userNameText.textContent = nameFromLocalStorage
  } <span class="hljs-keyword">else</span> {
    userNameText.textContent = <span class="hljs-string">"No name data in local storage"</span>
  }
}

displayUserName()
</code></pre>
<p>The <code>displayUserName</code> function gets <code>nameFromLocalStorage</code> using the <code>getItem()</code> method. If the value exists in local storage, we set it as the <code>textContent</code> of the <code>userNameText</code> element. If it's <code>null</code> or doesn't exist, then we set <code>textContent</code> to the string <em>"No name data in local storage"</em>.</p>
<h3 id="heading-code-example-for-session-storage">Code Example for Session Storage</h3>
<p>Now, let's do the same thing for the <code>age</code> value. The only difference here will be using session storage instead of local storage.</p>
<pre><code class="lang-javascript">
saveAgeButton.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> userAge = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".age"</span>).value
  userAgeText.textContent = userAge
  sessionStorage.setItem(<span class="hljs-string">"age"</span>, userAge)
})

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayUserAge</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> ageFromSessionStorage = sessionStorage.getItem(<span class="hljs-string">"age"</span>)

  <span class="hljs-keyword">if</span> (ageFromSessionStorage) {
    userAgeText.textContent = ageFromSessionStorage
  } <span class="hljs-keyword">else</span> {
    userAgeText.textContent = <span class="hljs-string">"No age data in session storage"</span>
  }
}

displayUserAge()
</code></pre>
<p>The <code>setItem</code> and <code>getItem</code> methods also works for session storage.</p>
<h3 id="heading-demo">Demo:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/demo.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Local storage and session storage demo.</em></p>
<p>As you can see from the demo above, when you close and reopen the page, the <code>name</code> data from local storage persists. But the <code>age</code> data from session storage is cleared once the page closes.</p>
<p><a target="_blank" href="https://stackblitz.com/edit/vitejs-vite-hb86sa?file=index.html,main.js&amp;terminal=dev">Try your hands on the code sample on StackBlitz</a></p>
<h2 id="heading-how-to-view-local-storage-in-devtools">How to View Local Storage in DevTools</h2>
<p>You can follow the steps below to inspect the contents of local storage in your browser's developer tools.</p>
<p>First, open DevTools. You can do that by right clicking on the web page and selecting "Inspect".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/STEP-ONE.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Demo of how to open the DevTools.</em></p>
<p>Then, select the "Application" tab on the DevTools panel. Depending on your browser, this panel may have a different name. For example, it's called "Storage" in Safari and Firefox.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/STEP-TWO.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Demo of how to open the "Application" panel in DevTools.</em></p>
<p>Locate the "Storage" section on the sidebar showing a list of the various web storage options.</p>
<p>Click on "Local Storage" to expand and view its contents.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/STEP-THREE.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Demo of how to open the local storage tab in the storage panel.</em></p>
<p>You can click on individual items to view the corresponding key-value pair.</p>
<h2 id="heading-benefits-of-using-local-storage">Benefits of Using Local Storage</h2>
<p>The following are some of the benefits local storage has over other storage mechanisms in modern web development.</p>
<ol>
<li><p><strong>Persistent data:</strong> When you use local storage, the stored data remains even when the user closes the tab or the browser. This is useful for saving user preferences, settings, and other relevant data. It can help create a seamless user experience.</p>
</li>
<li><p><strong>Offline access:</strong> You can use local storage as a means to cache data which can be accessed even with limited or no internet. This makes it a useful feature for apps that rely on caching data for offline use like news readers, productivity apps, and so on.</p>
</li>
<li><p><strong>More storage capacity:</strong> Compared to other storage means, local storage has a relatively high capacity. For example, cookies are limited to 4 kilobytes per domain. But local storage can store up to 5 megabytes of data per domain.</p>
</li>
</ol>
<h2 id="heading-limitations-of-using-local-storage">Limitations of Using Local Storage</h2>
<ol>
<li><p><strong>Stores only strings:</strong> As you learned earlier, local storage can only store string values. You can use the JSON <code>stringify</code> and <code>parse</code> methods to work around it. But some web developers may not prefer it as it can lead to writing complex code that’s difficult to debug.</p>
</li>
<li><p><strong>Security concerns:</strong> Data in the local storage can be prone to attacks like cross-site scripting (XSS). As such, you should be cautious when working with sensitive information. It’s advisable to assess security implications and consider other alternatives where necessary.</p>
</li>
<li><p><strong>Not accessible to web workers:</strong> Local storage is part of the Window object. As such, it’s tied to the main execution thread of the web page. This means it's not accessible to web workers. So if you run any background processes, you cannot use local storage within the web worker scripts.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Local storage is a feature in modern web browsers that makes it easy for web developers to store and persist data between browser sessions.</p>
<p>Compared to traditional cookies, it provides larger storage capacities. Also, unlike cookies, it does not rely on server-side processes. This reduces the need for frequent server requests and helps improve performance.</p>
<p>In this article, you learn about how to use local storage. We covered saving, retrieving, and deleting data from local storage. You also learned about some of the benefits of using local storage in your project, and some of its limitations too.</p>
<p>Thanks for reading. And happy coding! For more in-depth tutorials, feel free to <a target="_blank" href="https://www.youtube.com/@DevAfterHours">subscribe to my YouTube channel</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Web Storage Works – Local vs Session Storage Explained ]]>
                </title>
                <description>
                    <![CDATA[ Anyone who works with the web needs to store data for a later use. Backend developers have some powerful databases in their toolkit. But if you are a frontend developer, you can still store and process data using web storage. In this article, you'll ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-web-storage-works/</link>
                <guid isPermaLink="false">66bf4ac87df110118a932070</guid>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ storage ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tooba Jamal ]]>
                </dc:creator>
                <pubDate>Wed, 12 Oct 2022 14:08:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/webstorage-1-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Anyone who works with the web needs to store data for a later use. Backend developers have some powerful databases in their toolkit. But if you are a frontend developer, you can still store and process data using web storage.</p>
<p>In this article, you'll learn what is a web storage, the different types of web storage, and when to use each one of them.</p>
<h2 id="heading-what-is-web-storage">What is Web Storage?</h2>
<p>Web storage is an HTML5 feature that allows you to store data in key value pairs in the browser. This enables applications to store data in the client side so you can access it or manipulate it later. All data stored in web storage stays in the browser and is not transferred anywhere else.</p>
<h2 id="heading-types-of-web-storage">Types of web storage</h2>
<p>The two main types of web storage are‌‌ local storage‌‌ and session storage‌‌. Each one has its own unique characteristics. </p>
<p>But one thing they have in common is that they store the data in the particular browser the user uses to access the webpage. You won't be able to access the same data through another browser. </p>
<p>Now let's discuss both of them in detail.</p>
<h3 id="heading-local-storage">Local Storage</h3>
<p>Local storage can store 5MB of data per app for the lifetime of the app. Closing the browser will not affect the data in any way – it stays there unless you delete it. </p>
<p>You can only access the local storage object through <code>localStorage</code>. The methods you can use to perform operations on the localStorage object are:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">localStorage</span> <span class="hljs-comment">// to access the localStorage object </span>
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'name'</span>, <span class="hljs-string">'John'</span>) <span class="hljs-comment">// sets name equal to john localStorage.getItem('name') // "John" </span>
<span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">'name'</span>) <span class="hljs-comment">// removes name from the localStorage localStorage.clear() // clears the localStorage</span>
</code></pre>
<p><code>localStorage.setItem()</code> takes a key and value as parameters and sets a new item in the local storage object equal to the given key value pair. </p>
<p><code>localStorage.getItem()</code> takes a key as a parameter and returns the value stored to that key in the storage. </p>
<p><code>localStorage.clear()</code> clears the whole localStorage object.</p>
<p><code>localStorage.removeItem()</code> takes in a key as a parameter and removes the corresponding key-value pair. ‌‌</p>
<p>Any item that you store in localStorage will be stored as a string. This means that you need to convert other data types such as arrays or objects to strings – otherwise you lose their structure. </p>
<p>See the example below:       </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> scores = [<span class="hljs-number">10</span>, <span class="hljs-number">8</span>, <span class="hljs-number">6</span>, <span class="hljs-number">3</span>, <span class="hljs-number">9</span>] 
<span class="hljs-keyword">const</span> scoresJSON = <span class="hljs-built_in">JSON</span>.stringify(scores) 
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'scores'</span>, scoresJSON) 
<span class="hljs-built_in">localStorage</span> <span class="hljs-comment">// output &gt;&gt; {scores: '[10, 8, 6, 3, 9]', length: 1}</span>
</code></pre>
<p>In the example above, we first created an array score, then converted it into a string using JSON.stringify(), and finally saved the stringified scores array in localStorage. </p>
<p>Take your time to have a look at the output I get when I run the same code snippet in my browser console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/localstorage-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example code in browser console</em></p>
<p>Note that the key scores has a value equal to our stringified scores array. But if we don't convert the scores array into a string, our array will loose it's structure and the items will be saved as a string like below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> scores = [<span class="hljs-number">10</span>, <span class="hljs-number">8</span>, <span class="hljs-number">6</span>, <span class="hljs-number">3</span>, <span class="hljs-number">9</span>] 
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'scores'</span>, scores) 
<span class="hljs-built_in">localStorage</span> <span class="hljs-comment">// output &gt;&gt; {scores: '10, 8, 6, 3, 9', length: 1}</span>
</code></pre>
<p>Let's also run the code in the browser console to see what is logs to the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/localstorage-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Saving an array without converting it into a string</em></p>
<p>See how our scores array is converted into a string when we do not convert it into a string using JSON.stringify()?</p>
<h3 id="heading-session-storage">Session Storage</h3>
<p>Session storage allows you to store data in the browser depending on the system memory and the data stored in the browser until the browser is closed. In other words, closing the browser will clear all the data stored in session storage. </p>
<p>Like localStorage, you can access session storage by typing sessionStorage in the browser console.</p>
<pre><code class="lang-javascript">sessionStorage <span class="hljs-comment">// access the session storage </span>
sessionStorage.setItem(<span class="hljs-string">'name'</span>, <span class="hljs-string">'John'</span>) <span class="hljs-comment">// add name to session storage with value john </span>
sessionStorage.getItem(<span class="hljs-string">'name'</span>) <span class="hljs-comment">// get the name item from session storage sessionStorage.removeItem('name') // remove name item from the session storage sessionStorage.clear() // clear the session storage</span>
</code></pre>
<p><code>sessionStorage.setItem()</code> takes a key and value as parameters and sets a new item in the local storage object equal to the given key value pair.</p>
<p><code>sessionStorage.getItem()</code> takes key as a parameter and returns the value stored to that key in the storage. </p>
<p><code>sessionStorage.removeItem()</code> takes in a key as parameter and removes the corresponding key-value pair. </p>
<p><code>sessionStorage.clear()</code> clears the whole localStorage object. ‌‌</p>
<p>Like localStorage, any item stored in sessionStorage will be stored as a string. This means we need to convert them into strings before storing in the sessionStorage.</p>
<h2 id="heading-web-storage-example-use-cases">Web Storage Example Use Cases</h2>
<p>You can use <strong>local storage</strong> when you want your data to be made available when the user revisits the web page, such as for a shopping cart or game/quiz score. Just keep in mind that the information saved in local storage should not be sensitive.‌‌</p>
<p>You can use <strong>session storage</strong> when the data that needs to be saved is sensitive. User authentication is an example of data that you would like to clear as soon as the user closes the tab.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you have learned the modern ways of storing temporary data in the browser. I hope this has helped you understand how and when to use both types of web storage in your projects. </p>
<p>Interested in connecting on LinkedIn? Hit me up at <a target="_blank" href="https://www.linkedin.com/in/tooba-jamal/">Tooba Jamal</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use localStorage with React Hooks to Set and Get Items ]]>
                </title>
                <description>
                    <![CDATA[ localStorage is a web storage object that allows JavaScript sites and apps to keep key-value pairs in a web browser with no expiration date. This means the data survives page refreshes (sessionStorage) and even browser restarts. This indicates that t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-localstorage-with-react-hooks-to-set-and-get-items/</link>
                <guid isPermaLink="false">66d45fb5230dff0166905816</guid>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joel Olawanle ]]>
                </dc:creator>
                <pubDate>Tue, 22 Feb 2022 14:53:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/Yellow-and-Purple-Geometric-Covid-19-General-Facts-Twitter-Post.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>localStorage is a web storage object that allows JavaScript sites and apps to keep key-value pairs in a web browser with no expiration date.</p>
<p>This means the data survives page refreshes (sessionStorage) and even browser restarts. This indicates that the data stored in the browser will remain even when the browser window is closed.</p>
<p>In basic terms, local storage enables developers to store and retrieve data in the browser.</p>
<p>It is critical to understand, though, that using localStorage as a database for your project is not a good practice, since data will be lost when the user clears the cache, among other things.</p>
<p>Developers frequently use localStorage for adding a dark mode feature to an application, saving a to-do item, or persisting a user's form input values, among many other scenarios.</p>
<p>In this post, we'll take a look at how to use localStorage with React hooks to set and get items easily.</p>
<h3 id="heading-heres-an-interactive-scrim-about-how-to-use-localstorage-with-react-hooks-to-set-and-get-items">Here's an interactive scrim about how to use localStorage with React Hooks to set and get items:</h3>
<div class="embed-wrapper"><iframe src="https://scrimba.com/scrim/crdLpnSG?embed=freecodecamp,mini-header" width="100%" height="480" title="Embedded content" loading="lazy"></iframe></div>

<h2 id="heading-what-are-react-hooks">What are React Hooks?</h2>
<p>React Hooks are JavaScript functions that you may import from the React package to add capabilities to your components.</p>
<p>Hooks allow React developers to use state and lifecycle methods within functional components. They also operate with existing code, making them easily adoptable into a codebase.</p>
<p>We will need two hooks in order to use localStorage with react hooks:</p>
<ul>
<li><p><code>useState()</code> – The state of your application is guaranteed to change at some time. The <code>useState()</code> hook is a function that accepts one parameter, the initial state (which might be the value of a variable, an object, or any other sort of data in your component), and returns two values: the current state and a function that can be used to update the state.</p>
</li>
<li><p><code>useEffect()</code> – The Effect Hook is activated by default after the first render and each time the state is changed. As the names suggest, it is used to perform an effect each time the state changes. This hook is great for configuring listeners, retrieving data from the API, and deleting listeners before the component is removed from the DOM.</p>
</li>
</ul>
<h2 id="heading-how-to-implement-localstorage-in-react">How to Implement localStorage in React</h2>
<p>localStorage provides us with access to a browser's storage object, which includes five methods:</p>
<ul>
<li><p><code>setItem()</code>: This method is used to add a key and a value to localStorage.</p>
</li>
<li><p><code>getItem()</code>: This method is used to get an item from localStorage using the key.</p>
</li>
<li><p><code>removeItem()</code>: This technique is used to delete an item from localStorage based on its key.</p>
</li>
<li><p><code>clear()</code>: This technique is used to delete all instances of localStorage.</p>
</li>
<li><p><code>key()</code>: When you supply a number, it aids in the retrieval of a localStorage key.</p>
</li>
</ul>
<p>In this post, we will only consider the most popular methods, which are the first two methods.</p>
<h3 id="heading-how-to-use-the-setitem-method">How to Use the <code>setItem()</code> Method</h3>
<p>By giving values to a key, this technique is used to store objects in localStorage. This value can be of any datatype, including text, integer, object, array, and so on.</p>
<p>It is vital to remember that in order to store data in localStorage, you must first stringify it with the <code>JSON.stringify()</code> function.</p>
<pre><code class="lang-bash">const [items, setItems] = useState([]);

useEffect(() =&gt; {
  localStorage.setItem(<span class="hljs-string">'items'</span>, JSON.stringify(items));
}, [items]);
</code></pre>
<p>In the above code, we first created a state and assigned it an empty array (yours could be any other datatype). Second, we used <code>useEffect()</code> to add objects to localStorage whenever the value of our state changed. We did this by passing the state as the second argument.</p>
<p>Basically, this is the major code responsible for adding key-value pairs to localStorage:</p>
<pre><code class="lang-bash">localStorage.setItem(<span class="hljs-string">'items'</span>, JSON.stringify(items));
</code></pre>
<p>Simply put, the preceding code names the key (items) and then assigns a value to it, but we had to first ensure that the data we were adding was a JSON string.</p>
<p>We use JSON.stringify() to convert a JSON object to JSON text stored in a string, which can then be transmitted to the web server.</p>
<p><img src="https://paper-attachments.dropbox.com/s_EAEEAE9063B0CA7CBC6574F36123E82B36B6C1EC3724A86DA7C0B4C67C2DD652_1645380076460_explaining+useeffect+local+storage.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Structure of how hooks works with localstorage to set items</em></p>
<p>How to Use the <code>getItem(</code>) Method</p>
<p>This method retrieves objects from localStorage. There are other methods to accomplish this with React, but we will use the <code>useEffect()</code> hook because it is the best one.</p>
<p>The <code>useEffect()</code> hook helps us fetch all items on first render, which means that when the component mounts or re-renders, it obtains all of our data from localStorage.</p>
<p>Note that this is why we passed in an empty second argument.</p>
<pre><code class="lang-bash">const [items, setItems] = useState([]);

useEffect(() =&gt; {
  const items = JSON.parse(localStorage.getItem(<span class="hljs-string">'items'</span>));
  <span class="hljs-keyword">if</span> (items) {
   setItems(items);
  }
}, []);
</code></pre>
<p>It is important to remember that when we stored the data, we first converted it to a JSON string. This means that in order for us to now make use of it, we need to convert JSON string back to a JSON object. We do this with the <code>JSON.parse()</code> method.</p>
<p><img src="https://paper-attachments.dropbox.com/s_EAEEAE9063B0CA7CBC6574F36123E82B36B6C1EC3724A86DA7C0B4C67C2DD652_1645369611908_explaining+useeffect+local+storage2.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Structure of how hooks works with localstorage to get items</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we learnt how to use localStorage with React hooks, when to use it, and which hook to use.</p>
<p>If you want to see how this works in practice, you can get the source code for a simple to-do list app that makes use of localStorage and these hooks <a target="_blank" href="https://github.com/olawanlejoel/Todo-App">here</a>.</p>
<p>You can learn more about <a target="_blank" href="https://joelolawanle.com/posts/understanding-state-props-react-key-differences-explained">state and props in this detailed article</a> written by me. You can also check all articles written by me in this <a target="_blank" href="https://joelolawanle.com/contents">content repository</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Persist a Logged-in User in React ]]>
                </title>
                <description>
                    <![CDATA[ By Adebola Adeniran If you run a quick Google search for persisting a logged-in user in React (or keeping a user logged in in React), you don't get a lot of straightforward results. There aren't really any easy to follow examples on how to achieve th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-persist-a-logged-in-user-in-react/</link>
                <guid isPermaLink="false">66d45d5fc17d4b8ace5b9eb2</guid>
                
                    <category>
                        <![CDATA[ keep a user signed in ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localstorage ]]>
                    </category>
                
                    <category>
                        <![CDATA[ login forms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 15 Jun 2020 21:39:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/Slice-3-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adebola Adeniran</p>
<p>If you run a quick Google search for persisting a logged-in user in React (or keeping a user logged in in React), you don't get a lot of straightforward results. There aren't really any easy to follow examples on how to achieve this. So I decided I had to write that simple guide.</p>
<p>You may have done a search on this and saw the word <strong>localStorage</strong> being thrown around. Yes, we'll be using <strong>localStorage</strong> but I'm going to show you exactly how it's done. </p>
<h2 id="heading-some-notes-on-localstorage">Some notes on localStorage.</h2>
<ol>
<li><strong>localStorage</strong> is the browser's database. The data is stored inside your browser in your computer's memory.</li>
<li><strong>localStorage</strong> is specific to an origin. In other words, the localStorage for one website cannot be accessed by another.</li>
</ol>
<h2 id="heading-initial-setup">Initial setup</h2>
<p>Let's get started. I've deployed a simple express server to Heroku for use in testing this application.</p>
<ol>
<li>Create a new React application and head into the <strong><code>&lt;App /&gt;</code></strong> component. </li>
<li>Install axios using <code>npm install axios</code> and import it inside <strong><code>&lt;App /&gt;</code></strong></li>
<li>Next, create a simple login form that accepts a username and password. </li>
</ol>
<pre><code><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [username, setUsername] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [user, setUser] = useState()

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> e =&gt; {

  };

<span class="hljs-comment">// if there's a user show the message below</span>
  <span class="hljs-keyword">if</span> (user) {
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{user.name} is loggged in<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  }

  <span class="hljs-comment">// if there's no user, show the login form</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"username"</span>&gt;</span>Username: <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{username}</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"enter a username"</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">target</span> }) =&gt;</span> setUsername(target.value)}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"password"</span>&gt;</span>password: <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"enter a password"</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">target</span> }) =&gt;</span> setPassword(target.value)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><p>As you can see, we've defined an asynchronous <strong>handleSubmit</strong> function to process the login request. We've also defined a conditional that displays a <strong>user.name is logged in</strong> message if we have a user, and the login form if we do not have a user.</p>
<p>Next, let's complete the function. This function will work in the following steps:</p>
<ol>
<li>Send the login details to the server.</li>
<li>If the request is successful (async-await), store the user information in                    localStorage and set the State of the User.</li>
</ol>
<h2 id="heading-handle-the-login-event">Handle the login event</h2>
<p>Let's define the <strong>handleSubmit</strong> event handler.</p>
<pre><code>  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> e =&gt; {
    e.preventDefault();
    <span class="hljs-keyword">const</span> user = { username, password };
    <span class="hljs-comment">// send the username and password to the server</span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(
      <span class="hljs-string">"http://blogservice.herokuapp.com/api/login"</span>,
      user
    );
    <span class="hljs-comment">// set the state of the user</span>
    setUser(response.data)
    <span class="hljs-comment">// store the user in localStorage</span>
    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'user'</span>, response.data)
    <span class="hljs-built_in">console</span>.log(response.data)
  };
</code></pre><p>Note: Use a <strong>tryCatch</strong> block to handle errors in async functions.</p>
<p>Now that our function is done, you can run <strong>npm start</strong> to test out your app. Login with the <strong>username</strong>: user2, <strong>password</strong>: password.</p>
<p>You should receive the following as a response. The <em>userId</em>, <em>token</em> and <em>username</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-52.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-check-if-a-user-has-previously-logged-in">Check if a user has previously logged in</h2>
<p>Next, we want a way to check if there's a user logged in each time the App loads. For that, we use the useEffect hook. </p>
<pre><code> useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> loggedInUser = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">"user"</span>);
    <span class="hljs-keyword">if</span> (loggedInUser) {
      <span class="hljs-keyword">const</span> foundUser = <span class="hljs-built_in">JSON</span>.parse(loggedInUser);
      setUser(foundUser);
    }
  }, []);
</code></pre><p>Remember to use an empty dependency array in your useEffect hook so that it checks if there's a logged in user the first time the app loads.</p>
<p>Now our app should work perfectly. We get the page below after a user has logged in for the first time and their details are stored. If you refresh the page, you'll see that our user stays logged in and the logged in page continues to show.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/image-55.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As a bonus tip, here's how to implement logout.</p>
<h2 id="heading-implementing-logout-functionality">Implementing Logout functionality</h2>
<p>For logging out, we simply empty the user state and remove the user from localStorage. </p>
<p>Let's implement that. </p>
<p>First, we create a logout button</p>
<pre><code>&lt;button onClick={handleLogout}&gt;logout&lt;/button&gt;
</code></pre><p>Then, we create the logout function.</p>
<pre><code><span class="hljs-keyword">const</span> handleLogout = <span class="hljs-function">() =&gt;</span> {
    setUser({});
    setUsername(<span class="hljs-string">""</span>);
    setPassword(<span class="hljs-string">""</span>);
    <span class="hljs-built_in">localStorage</span>.clear();
  };
</code></pre><p>And that's it, we're done.</p>
<p>Here's a link to the full <a target="_blank" href="https://gist.github.com/onedebos/bbf7cd4634bce53103c1cfefa6164637">gist</a> on GitHub. You can follow me there for more updates.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
