<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Chioma Halim</title>
    <description>The latest articles on Forem by Chioma Halim (@audreyhal).</description>
    <link>https://forem.com/audreyhal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F258359%2F058e10ff-38d0-4e9d-89ca-a2d9113bd973.png</url>
      <title>Forem: Chioma Halim</title>
      <link>https://forem.com/audreyhal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/audreyhal"/>
    <language>en</language>
    <item>
      <title>All It Took Was npm install (Axios Attack)</title>
      <dc:creator>Chioma Halim</dc:creator>
      <pubDate>Mon, 13 Apr 2026 09:43:00 +0000</pubDate>
      <link>https://forem.com/audreyhal/all-it-took-was-npm-install-axios-attack-2dk2</link>
      <guid>https://forem.com/audreyhal/all-it-took-was-npm-install-axios-attack-2dk2</guid>
      <description>&lt;p&gt;All it took was &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;During the Axios attack, that was enough to run malicious code on your machine.&lt;/p&gt;

&lt;p&gt;In late March 2026, one of the most widely used JavaScript libraries in the world, Axios, was at the center of a serious supply chain attack.&lt;/p&gt;

&lt;p&gt;Let’s break down what happened, why it matters, and what you can do to better protect your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of the attack
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://x.com/feross/status/2038807290422370479?s=46&amp;amp;t=WAH7UYi429ao1JsFbVCBqg" rel="noopener noreferrer"&gt;On March 31, 2026&lt;/a&gt;, attackers compromised an &lt;a href="https://github.com/axios/axios" rel="noopener noreferrer"&gt;Axios&lt;/a&gt; maintainer’s npm account and published two malicious versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;axios@1.14.1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;axios@0.30.4&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These versions looked legitimate but included a hidden dependency (&lt;code&gt;plain-crypto-js&lt;/code&gt;) that executed a malicious script during install.&lt;/p&gt;

&lt;p&gt;When a developer or CI system ran &lt;code&gt;npm install axios@1.14.1&lt;/code&gt;, npm resolved the dependency tree, pulled in the malicious package, and automatically executed its &lt;code&gt;postinstall&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;This script downloaded a cross-platform (macOS, Linux, and Windows) Remote Access Trojan (RAT), giving attackers remote access to the machine, the ability to execute commands, and access to sensitive data. It also cleaned up traces afterward to avoid detection.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;The malicious versions were live for only a few hours (2–3 hours)&lt;/li&gt;
&lt;li&gt;Axios sees ~100M weekly downloads, creating massive exposure&lt;/li&gt;
&lt;li&gt;The malicious code never appeared in the GitHub repo, bypassing review and CI&lt;/li&gt;
&lt;li&gt;The attack required only running your install step&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  First line of defense: Your Lockfile
&lt;/h2&gt;

&lt;p&gt;Your lockfile (package-lock.json, pnpm-lock.yaml, yarn.lock) is your first real line of defense against supply chain attacks. It doesn’t make your dependencies safe, it makes them predictable.&lt;/p&gt;

&lt;p&gt;Without it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every install asks the registry: “what’s the latest allowed version right now?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every install says: “give me exactly what we already trusted before”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why this matters
&lt;/h3&gt;

&lt;p&gt;Version ranges like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"axios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.14.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;don’t point to a single version, they define a range of possible versions.&lt;/p&gt;

&lt;p&gt;So every time dependencies are resolved, you’re effectively trusting future publishes you haven’t seen yet. That’s the real risk: not just what you depend on today, but what could be published tomorrow.&lt;/p&gt;

&lt;p&gt;A lockfile removes that uncertainty by freezing the exact version and dependency graph at a point in time. Instead of pulling in whatever is new, your installs remain consistent and repeatable. New releases don’t affect you unless you choose to update.&lt;/p&gt;

&lt;h3&gt;
  
  
  The limits of a lockfile
&lt;/h3&gt;

&lt;p&gt;A lockfile is not permanent protection. It only works as long as you don’t trigger a re-resolution, and that happens more often than most teams realize.&lt;br&gt;
Some actions will always refresh your dependency tree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deleting or regenerating the lockfile&lt;/li&gt;
&lt;li&gt;Running update commands&lt;/li&gt;
&lt;li&gt;Pulling in a new lockfile from a teammate, bot, or CI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other changes can trigger it indirectly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding or updating a dependency&lt;/li&gt;
&lt;li&gt;Installing a package that depends on Axios&lt;/li&gt;
&lt;li&gt;Fixing an out-of-sync lockfile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key point is this:  You don’t have to update Axios for its version to change. &lt;/p&gt;

&lt;p&gt;Your dependency tree is not a flat list, it’s a graph and changes in one part of the tree can propagate and affect other parts, even when you haven’t touched them directly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Second line of defense: pnpm 10 safeguards
&lt;/h2&gt;

&lt;p&gt;A lockfile controls what gets installed. But incidents like the Axios attack show that’s only half the problem.&lt;/p&gt;

&lt;p&gt;You also need to control what runs during installation. This is where &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt;&lt;br&gt;
comes in.&lt;/p&gt;

&lt;p&gt;pnpm is a JavaScript package manager known for its performance and efficient use of disk space. In recent versions, especially v10, it has also introduced safeguards that directly address supply chain risk by limiting what dependencies are allowed to do at install time.&lt;/p&gt;

&lt;p&gt;pnpm has been actively investing in this area. You can explore the full details on &lt;a href="https://pnpm.io/supply-chain-security" rel="noopener noreferrer"&gt;the official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Delay exposure to new releases
&lt;/h3&gt;

&lt;p&gt;One of the simplest ways to reduce risk is to avoid installing packages the moment they’re published.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pnpm-workspace.yaml&lt;/span&gt;
&lt;span class="na"&gt;minimumReleaseAge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1440&lt;/span&gt; &lt;span class="c1"&gt;# 24 hours&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This introduces a delay before newly published versions are considered installable. In practice, it helps avoid short-lived malicious releases that are quickly discovered and removed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Control install-time execution
&lt;/h3&gt;

&lt;p&gt;Dependencies are not just code you install, they can execute code during installation through scripts like &lt;code&gt;postinstall&lt;/code&gt;.&lt;br&gt;
That’s exactly what the Axios attack exploited.&lt;br&gt;
pnpm v10 changes the default behavior so that &lt;em&gt;dependencies do not run install scripts unless explicitly allowed&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This removes an entire class of attacks where malicious code executes during install. If certain packages legitimately require build scripts, you can explicitly allow them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;allowBuilds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;esbuild&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sharp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shifts execution from implicit trust to explicit approval.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Lockfiles help you to control what gets installed&lt;/li&gt;
&lt;li&gt;pnpm safeguards help control what is allowed to run&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they reduce both exposure and execution risk.&lt;/p&gt;

</description>
      <category>npm</category>
      <category>webdev</category>
      <category>cybersecurity</category>
      <category>node</category>
    </item>
    <item>
      <title>Why Your Iframe Fails (OAuth, Sandbox &amp; Cross-Origin Security Explained)</title>
      <dc:creator>Chioma Halim</dc:creator>
      <pubDate>Tue, 17 Mar 2026 23:55:52 +0000</pubDate>
      <link>https://forem.com/audreyhal/why-your-iframe-fails-oauth-sandbox-cross-origin-security-explained-3ifj</link>
      <guid>https://forem.com/audreyhal/why-your-iframe-fails-oauth-sandbox-cross-origin-security-explained-3ifj</guid>
      <description>&lt;p&gt;Embedding third-party content with an iframe is straightforward until it suddenly stops working.&lt;/p&gt;

&lt;p&gt;Some pages refuse to render, authentication flows fail, and redirects behave unexpectedly. In most cases, the problem isn’t your code. It’s the browser enforcing security rules around embedded content.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll break down why these restrictions exist and how to work with them. You’ll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why OAuth does not work inside iframes&lt;/li&gt;
&lt;li&gt;How CSP and &lt;code&gt;X-Frame-Options&lt;/code&gt; control embedding&lt;/li&gt;
&lt;li&gt;How the &lt;code&gt;sandbox&lt;/code&gt; attribute restricts iframe behavior&lt;/li&gt;
&lt;li&gt;How to safely communicate between an iframe and its parent using postMessage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is an iframe?
&lt;/h2&gt;

&lt;p&gt;An iframe (Inline Frame) is an HTML element that embeds another webpage or external content inside your current page.&lt;/p&gt;

&lt;p&gt;It works like a window that displays content from a different source without redirecting the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;iframe&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;600&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;400&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Example site&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/iframe&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;Some sites intentionally block being loaded inside an iframe. This protects users from clickjacking attacks, where malicious sites visually disguise login forms or sensitive actions. To allow embedding of your site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the CSP &lt;code&gt;frame-ancestors&lt;/code&gt; directive with trusted parent domains&lt;/li&gt;
&lt;li&gt;Ensure &lt;code&gt;X-Frame-Options&lt;/code&gt; isn't set to &lt;code&gt;DENY&lt;/code&gt; or &lt;code&gt;SAMEORIGIN&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practice&lt;/strong&gt;: Only allow trusted origins to enable secure iframe embedding.&lt;/p&gt;

&lt;h2&gt;
  
  
  OAuth Restrictions in Iframes
&lt;/h2&gt;

&lt;p&gt;OAuth flows generally do not work inside iframes due to modern browser security controls:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Clickjacking Protection&lt;/strong&gt;&lt;br&gt;
Most providers send headers like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;X-Frame-Options&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Security-Policy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These block login pages from being embedded, preventing malicious framing attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Third-Party Cookie Blocking&lt;/strong&gt;&lt;br&gt;
Browsers restrict cookies in cross-site iframes, which breaks the session handling required for OAuth redirects and state validation. This affects major providers like Google, Facebook, GitHub, etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;p&gt;OAuth flows should run in a top-level browsing context, not inside an iframe. e.g&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redirect OAuth in the Parent Window
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inside click handler in iframe site&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;authUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then allow navigation using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;iframe&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SITE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow-top-navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/iframe&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Open OAuth in a New Tab:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// iframe site&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authLink&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allow popups using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;iframe&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SITE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allow-popups&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/iframe&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Iframe &lt;code&gt;sandbox&lt;/code&gt; Attribute
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;sandbox&lt;/code&gt; attribute is a security feature that restricts what embedded content can do. Adding &lt;code&gt;sandbox&lt;/code&gt; with no value applies all restrictions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No scripts&lt;/li&gt;
&lt;li&gt;No form submissions&lt;/li&gt;
&lt;li&gt;Cannot navigate the top-level window&lt;/li&gt;
&lt;li&gt;No popups&lt;/li&gt;
&lt;li&gt;No automatic features (autoplay, pointer lock, etc.).&lt;/li&gt;
&lt;li&gt;By passing a value, you can determine what behaviours you'd like to permit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Sandbox Values for an iframe
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;allow-scripts&lt;/code&gt; — Runs JavaScript inside the iframe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allow-forms&lt;/code&gt; — Allows form submissions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allow-popups&lt;/code&gt; — Enables opening new windows via window.open()&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allow-same-origin&lt;/code&gt; — Treats iframe content as same-origin (cookies + DOM access)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allow-top-navigation&lt;/code&gt; — Lets the iframe redirect the top-level page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allow-top-navigation-by-user-activation&lt;/code&gt;— Allows top navigation only after a user click/tap&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allow-modals&lt;/code&gt; — Enables modal dialogs like alert, confirm, and prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Communication Between an iframe and It's Parent
&lt;/h2&gt;

&lt;p&gt;When embedding an iframe, you may need communication with the parent page. For example, to notify about user actions. Due to the &lt;strong&gt;Same-Origin Policy&lt;/strong&gt;, the parent and iframe cannot directly access each other's DOM or JS if they are on different origins. A standard approach to enabling communication is by using : &lt;code&gt;window.postMessage()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sending a Message (iframe → parent)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loginSuccess&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://parent-site.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Listening for Messages (parent)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://iframe-site.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Always validate &lt;code&gt;event.origin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Never trust incoming data blindly&lt;/li&gt;
&lt;li&gt;Avoid using &lt;code&gt;"*"&lt;/code&gt; as the target origin unless absolutely necessary&lt;/li&gt;
&lt;li&gt;Ensure the iframe isn't sandboxed without &lt;code&gt;allow-scripts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>security</category>
    </item>
    <item>
      <title>Push Notifications with Firebase in React.js</title>
      <dc:creator>Chioma Halim</dc:creator>
      <pubDate>Wed, 01 Dec 2021 22:29:32 +0000</pubDate>
      <link>https://forem.com/audreyhal/push-notifications-with-firebase-in-reactjs-1f9i</link>
      <guid>https://forem.com/audreyhal/push-notifications-with-firebase-in-reactjs-1f9i</guid>
      <description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Push notifications are &lt;strong&gt;alerts that are "pushed" to a user's device by apps, even when those apps aren't open&lt;/strong&gt;. In the case of web push notifications, the web app receives messages pushed to it from a server at any time. This includes when the application is active or inactive or not open in the browser and when the browser is inactive. Firebase Cloud Messaging is a cross-platform messaging solution that lets you reliably send these messages at no cost.&lt;/p&gt;
&lt;p&gt;In this tutorial, we are going to be walking through how to set up Firebase Cloud Messaging to receive web push notifications in your React.js app.&lt;/p&gt;

&lt;h3&gt;Firebase Setup&lt;/h3&gt;
&lt;p&gt;Create an account at &lt;a href="https://firebase.google.com" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://firebase.google.com" rel="noopener noreferrer"&gt;https://firebase.google.com&lt;/a&gt;, if you don't already have one. Upon successful account creation, you would be navigated to &lt;a href="https://console.firebase.google.com" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://console.firebase.google.com" rel="noopener noreferrer"&gt;https://console.firebase.google.com&lt;/a&gt; afterwards, where you can create a project by clicking on the &lt;strong&gt;Create a project&lt;/strong&gt; button and filling out the necessary fields.&lt;/p&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkqkweuh7c7xqqno1mgw.png" alt="Firebase Setup Image" width="800" height="390"&gt;

&lt;p&gt;Once project creation is done. Click on the created project and select the platform you want to connect the service to. Since we are working on a web project we can select the &lt;b&gt;web&lt;/b&gt; option by clicking on the (&lt;strong&gt;&amp;gt;&lt;/strong&gt;) icon. This would take us to an interface to &lt;strong&gt;Add Firebase to your web app. &lt;/strong&gt;After filling in the field for &lt;strong&gt;app nickname&lt;/strong&gt; and clicking the&lt;strong&gt; Register app &lt;/strong&gt;button, it should generate a configuration object that we'll need to pass to our React app in later steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwff49kjoiawnz7s8k2ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwff49kjoiawnz7s8k2ac.png" alt="Firebase Setup Image" width="800" height="390"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvoct5qvoz2zc6p0am9mx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvoct5qvoz2zc6p0am9mx.gif" alt="Firebase Setup GIF" width="500" height="234"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;Connecting Firebase Cloud Messaging to our Application&lt;/h3&gt;
&lt;p&gt;1. Install Firebase in your React project by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install firebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;2. Create a new file called &lt;code&gt;firebase.js&lt;/code&gt; and add the following lines of code :&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initializeApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Replace this firebaseConfig object with the configurations for the project you created on your firebase console. &lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;//... &lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Import Firebase's messaging module into the &lt;code&gt;firebase.js&lt;/code&gt; file:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getMessaging&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase/messaging&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getMessaging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;4. Create a function called &lt;code&gt;requestForToken&lt;/code&gt; that makes use of Firebase's &lt;a href="https://firebase.google.com/docs/reference/js/messaging_#gettoken" rel="noopener noreferrer"&gt;&lt;code&gt;getToken&lt;/code&gt;&lt;/a&gt; method. This lets you subscribe your app to push notifications. If notification permission has not been granted, this method will ask the user for notification permissions. Otherwise, it returns a token or rejects the promise due to an error.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//....&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getMessaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/messaging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//....&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestForToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;vapidKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REPLACE_WITH_YOUR_VAPID_KEY&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current token for client: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Perform any other necessary action with the token&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Show permission request UI&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No registration token available. Request permission to generate one.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;An error occurred while retrieving token. &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The &lt;code&gt;getToken&lt;/code&gt; method requires you to pass a &lt;em&gt;Voluntary Application Server Identification&lt;/em&gt; or &lt;em&gt;VAPID&lt;/em&gt; key. You can get it by following these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click on &lt;strong&gt;Project Settings&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;for your project from the Firebase console, then navigate to the &lt;strong&gt;Cloud Messaging&lt;/strong&gt; tab and scroll to the &lt;strong&gt;Web configuration&lt;/strong&gt; section. &lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Web Push certificates&lt;/strong&gt; tab, click on &lt;strong&gt;Generate key pair&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;5. Finally, you can link the &lt;code&gt;firebase.js&lt;/code&gt; file to the rest of your project by importing it where it's needed. In this case, we can create a &lt;code&gt;Notification&lt;/code&gt; component:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;requestForToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./firebase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;requestForToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="c1"&gt;//....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h4&gt;Additional Step: &lt;/h4&gt;
&lt;p&gt;The messaging service requires a &lt;code&gt;firebase-messaging-sw.js&lt;/code&gt; file to work fine. I'll explain more about this file in the &lt;strong&gt;Background Listener Setup &lt;/strong&gt;section of this guide. For now, create an empty file named &lt;code&gt;firebase-messaging-sw.js&lt;/code&gt; in the public folder of your project.&lt;/p&gt;
&lt;p&gt;Navigate to the browser console of your app to test if our app can connect to Firebase Cloud Messaging service. You should see the token that was received, if successful.&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9f098j2aceg3n9yffahi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9f098j2aceg3n9yffahi.png" alt="firebase-push-notification-image" width="800" height="371"&gt;&lt;/a&gt; &lt;/p&gt;


&lt;h4&gt;Something went wrong?&lt;/h4&gt;
&lt;p&gt;1.) If you got an error concerning &lt;em&gt;&lt;strong&gt;permissions not being granted but blocked instead&lt;/strong&gt;&lt;/em&gt;, you should make sure you set notifications permissions to &lt;em&gt;&lt;strong&gt;Allow&lt;/strong&gt;&lt;/em&gt; in your browser.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr5b905l5ddbuovlojua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr5b905l5ddbuovlojua.png" alt="firebase-push-notification-image" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.) If you got an error concerning a &lt;em&gt;&lt;strong&gt;missing required authentication credential&lt;/strong&gt;, &lt;/em&gt;then you probably passed the wrong &lt;strong&gt;VAPID_KEY&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv6f6fao1kjqcj401crn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv6f6fao1kjqcj401crn.png" alt="firebase-push-notification-image&amp;lt;br&amp;gt;
![firebase-push-notification-image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wd52pv94dphzsm2lwrxc.png)" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;Receiving Messages&lt;/h3&gt;
&lt;p&gt;Now that the initial setup is done, you'll need to configure message listeners. Foreground message listeners are called when the page has focus(i.e. when the user is on the browser tab containing our web app), while background message listeners are called when the user is on a different tab or even when the tab containing our app is closed.&lt;/p&gt;
&lt;h4&gt;Foreground Listener Setup&lt;/h4&gt;
&lt;p&gt;To handle messages when the app is in the foreground, you can make use of Firebase's &lt;code&gt;&lt;a href="https://firebase.google.com/docs/reference/js/messaging_#onmessage" rel="noopener noreferrer"&gt;onMessage&lt;/a&gt;&lt;/code&gt; method in your &lt;code&gt;firebase.js&lt;/code&gt; file:&lt;/p&gt;
&lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getMessaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMessage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/messaging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//......&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getMessaging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;//......&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMessageListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;payload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can then call the method in the &lt;code&gt;Notification&lt;/code&gt; component. For this tutorial, I'm making use of &lt;a href="https://react-hot-toast.com/" rel="noopener noreferrer"&gt;&lt;em&gt;react-hot-toast&lt;/em&gt;&lt;/a&gt; library to create a toast UI for displaying the notification details received from the message listener.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Toaster&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-hot-toast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;requestForToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMessageListener&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./firebase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNotification&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ToastDisplay&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ToastDisplay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/b&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;){&lt;/span&gt;
     &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="nf"&gt;requestForToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;onMessageListener&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setNotification&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;     
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toaster&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h4&gt;Background Listener Setup&lt;/h4&gt;
&lt;p&gt;To handle background messages, you'd need to make use of a &lt;strong&gt;service worker&lt;/strong&gt;. A service worker is a script that your browser runs in the background, separate from the web page, enabling features that do not require a web page or user interaction.&lt;/p&gt;
&lt;p&gt;You can go ahead to add the following lines of code to your &lt;code&gt;firebase-messaging-sw.js&lt;/code&gt; file :&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Scripts for firebase and firebase messaging&lt;/span&gt;
&lt;span class="nf"&gt;importScripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;importScripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize the Firebase app in the service worker by passing the generated config&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_API_KEY`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_AUTH_DOMAIN`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_PROJECT_ID`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;storageBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_STORAGE_BUCKET`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messagingSenderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_SENDER_ID`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_APP_ID`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;measurementId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`REPLACE_WITH_YOUR_FIREBASE_MESSAGING_MEASUREMENT_ID`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve firebase messaging&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onBackgroundMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Received background message &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// Customize notification here&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notificationTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notificationOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;notificationOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;Testing Notifications&lt;/h3&gt;
&lt;p&gt;To test whether the notifications are functional, you can trigger a test notification from the firebase console with the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On your project dashboard, scroll to the &lt;strong&gt;Cloud Messaging &lt;/strong&gt;section.&lt;/li&gt;
&lt;li&gt;Under the &lt;strong&gt;Notifications&lt;/strong&gt; tab, click on the &lt;strong&gt;New notification &lt;/strong&gt;button&lt;/li&gt;
&lt;li&gt;Fill in the information for &lt;strong&gt;Notification title&lt;/strong&gt; and &lt;strong&gt;Notification text&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Under the &lt;strong&gt;Device preview&lt;/strong&gt; section, click on &lt;strong&gt;Send test message&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In the popup that opens, enter the &lt;strong&gt;client token&lt;/strong&gt; that is logged in the console as the FCM registration token and press the &lt;strong&gt;+&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Make sure that the FCM token is checked and click on &lt;strong&gt;Test&lt;/strong&gt;. You could also decide to fill in the entire&lt;strong&gt; Compose notification&lt;/strong&gt; section and press the &lt;strong&gt;Review&lt;/strong&gt; button at the bottom of the page to have it sent to multiple target apps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you're on the browser tab with the app opened, you should see a notification pop up. &lt;/p&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86k1tryby1shaq5i5g78.png" alt="firebase-push-notification-image" width="800" height="551"&gt;&lt;br&gt;&lt;p&gt;While if the browser tab with the application isn't in focus, you should see a default system notification pop-up.&lt;/p&gt;
&lt;br&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvusgoz1bmrto727fm9t.png" alt="firebase-push-notification-image" width="800" height="369"&gt;&lt;br&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To see a notification banner when notifications are received in the background, make sure to turn on the feature for your browser under your system's notification settings.&lt;/p&gt;
&lt;br&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67vd8osmwt7lire8rv4u.png" alt="firebase-push-notification-image" width="800" height="430"&gt;&lt;br&gt;&lt;h3&gt;&lt;/h3&gt;
&lt;h4&gt;Something went wrong ?&lt;/h4&gt;
&lt;p&gt;There may be cases where a user doesn't get notifications immediately or at all. This can be due to a variety of reasons, some of which are covered &lt;a href="https://www.pushengage.com/why-your-web-push-notification-lower-reach-than-expected/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Repository Code&lt;/h4&gt;
&lt;p&gt; You can find the GitHub repo for this tutorial at &lt;a href="https://github.com/AudreyHal/React-Firebase-Cloud-Messaging-Demo" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://github.com/AudreyHal/React-Firebase-Cloud-Messaging-Demo" rel="noopener noreferrer"&gt;https://github.com/AudreyHal/React-Firebase-Cloud-Messaging-Demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>firebase</category>
    </item>
    <item>
      <title>Persisting Files in Javascript (React) Applications</title>
      <dc:creator>Chioma Halim</dc:creator>
      <pubDate>Wed, 24 Mar 2021 18:56:48 +0000</pubDate>
      <link>https://forem.com/audreyhal/persisting-files-in-javascript-react-applications-3fah</link>
      <guid>https://forem.com/audreyhal/persisting-files-in-javascript-react-applications-3fah</guid>
      <description>&lt;p&gt;While working on a React application, you might come across scenarios where you need to store some files on the client-side to be used across different views before sending them to the server or you may want to be able to store large amounts of data on the client-side for offline access. For any of these scenarios, we would need a mechanism to be able to persist these files appropriately in our browser. In this post, I'll be covering how that can be achieved.&lt;/p&gt;

&lt;h1&gt;
  
  
  What not to do
&lt;/h1&gt;

&lt;p&gt;Before we get into how to properly persist our files, we are going to be looking at the limitations of other methods that one might consider.&lt;/p&gt;

&lt;p&gt;This involves assigning values to variables that make up parts of the browser URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com/cakes?flavour=chocolate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For React applications with routing set up, it's fairly common to see some information being passed across components pointing to different routes. This information can be easily retrieved when after a page refresh as long as the route information remains unchanged.&lt;/p&gt;

&lt;p&gt;In the case of transmitting files, this won't work because URL params are in string formats and file objects aren't &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Serialization" rel="noopener noreferrer"&gt;serializable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Attempting to serialize the file in the first component and retrieving the parsed file object in the second component via URL params would return an object with missing file information.&lt;/p&gt;

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

&lt;p&gt;LocalStorage is a property that allows web applications to store data locally within the user's browser as key/value pairs  with no expiration date.&lt;/p&gt;

&lt;p&gt;It stores up to 5-10MB of data (depending on the browser) and making use of it is as easy as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jason&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Saves data to localStorage object&lt;/span&gt;

&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Retrieves data using key&lt;/span&gt;

&lt;span class="c1"&gt;//=&amp;gt;  'Jason'&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;LocalStorage can also only store data in string format. This presents a problem for storing files since files aren't serializable data types.&lt;/p&gt;

&lt;p&gt;It is possible to &lt;a href="https://www.tutorialspoint.com/convert-image-to-data-uri-with-javascript" rel="noopener noreferrer"&gt;convert image files into a base64 encoded data URI&lt;/a&gt;, which is a serialized format, and then proceed to save it in local storage. But this is not optimal because both data URI's and local storage have size limits across different browsers.&lt;/p&gt;

&lt;p&gt;Note: The same set of limitations apply for applications using a tool like Redux Persist, which is a library allowing developers to save the redux store in the localStorage of the browser. Both localStorage and &lt;a href="https://redux.js.org/style-guide/style-guide#do-not-put-non-serializable-values-in-state-or-actions" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; don't store non-serializable data types, like files.&lt;/p&gt;

&lt;h1&gt;
  
  
  What you can do
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Using IndexedDB
&lt;/h3&gt;

&lt;p&gt;IndexedDB is a local database provided by the browser. It is more powerful than local storage and lets you store large amounts of data. Unlike local storage, in which you can only store strings, it lets you store all data types, including objects.&lt;/p&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stores key-pair values:&lt;/strong&gt; It uses an object store to hold data. In the object store, the data is stored in the form of "key-value pairs". Each data record has its own corresponding primary key, which is unique and can't be repeated. Duplication of a primary key would result in an error being thrown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Asynchronous:&lt;/strong&gt; Operations with IndexedDB can be performed side by side with other user operations because it doesn't block the main browser thread, unlike localStorage, which is synchronous. This prevents reading and writing of large amounts of data from slowing down the performance of the web page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limits data access to the same domain:&lt;/strong&gt; Each database corresponds to the domain name that created it. The web page can only access the database which is under its own domain name, but not a cross-domain database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support transactions:&lt;/strong&gt; This means that as long as one of a series of the steps fails, the entire transaction will be canceled, and the database is rolled back to the state before the transaction occurred. So there is no case where only a part of the data is rewritten.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supports all data types:&lt;/strong&gt; IndexedDB isn't limited to storing just strings, but can also store anything that can be expressed in JavaScript, including &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Boolean" rel="noopener noreferrer"&gt;boolean&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Number" rel="noopener noreferrer"&gt;number&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String" rel="noopener noreferrer"&gt;string&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date" rel="noopener noreferrer"&gt;date&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object" rel="noopener noreferrer"&gt;object&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array" rel="noopener noreferrer"&gt;array&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp" rel="noopener noreferrer"&gt;regexp&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/undefined" rel="noopener noreferrer"&gt;undefined&lt;/a&gt;, and null. It also allows storing blobs and files, which applies to our use case in this tutorial.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IndexedDB API is low-level and may seem a bit daunting to use to some. For this reason, libraries such as &lt;a href="https://localforage.github.io/localForage/" rel="noopener noreferrer"&gt;localForage&lt;/a&gt;, &lt;a href="https://dexie.org/" rel="noopener noreferrer"&gt;dexie.js&lt;/a&gt;, &lt;a href="https://github.com/erikolson186/zangodb" rel="noopener noreferrer"&gt;ZangoDB&lt;/a&gt;, &lt;a href="https://pouchdb.com/" rel="noopener noreferrer"&gt;PouchDB&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/idb" rel="noopener noreferrer"&gt;idb&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/idb-keyval" rel="noopener noreferrer"&gt;idb-keyval&lt;/a&gt;, &lt;a href="https://jsstore.net/" rel="noopener noreferrer"&gt;JsStore&lt;/a&gt; and &lt;a href="https://github.com/google/lovefield" rel="noopener noreferrer"&gt;lovefield&lt;/a&gt; provide a simpler API that makes IndexedDB more programmer-friendly.&lt;/p&gt;

&lt;p&gt;I'm going to be demonstrating how to store an object using the LocalForage JavaScript library. This is a wrapper that provides a simple &lt;code&gt;name: value&lt;/code&gt; syntax for client-side data storage, which uses IndexedDB in the background but falls back to WebSQL and then localStorage in browsers that don't support IndexedDB.&lt;/p&gt;

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

&lt;p&gt;To install this, simply run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install localforage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LocalForage syntax imitates that of localStorage but with the &lt;a href="https://localforage.github.io/localForage/#data-api-setitem" rel="noopener noreferrer"&gt;ability to store many types of data&lt;/a&gt; instead of just strings. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;localForage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Saves data to an offline store&lt;/span&gt;

&lt;span class="nx"&gt;localForage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Retrieves item from the store&lt;/span&gt;

&lt;span class="c1"&gt;//=&amp;gt;  {&lt;/span&gt;
&lt;span class="c1"&gt;//     firstName:"John", &lt;/span&gt;
&lt;span class="c1"&gt;//     lastName:"Doe",&lt;/span&gt;
&lt;span class="c1"&gt;//   };&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using a Class Module Instance
&lt;/h3&gt;

&lt;p&gt;IndexedDB is great for offline storage and comes with a lot of capabilities but may seem like an overkill for simple instances where you simply want to persist some files into memory and access them temporarily.&lt;/p&gt;

&lt;p&gt;We can achieve this by creating a simple class module as a form of abstraction, then exposing its instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StoredFiles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;saveFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getFiles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;resetValues&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;uploads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StoredFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Creates an instance of StoredFiles class&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;uploads&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can easily import the uploads in any file we need and access the methods of StoredFiles. For saving the files in memory, we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveFiles&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterwards, we can retrieve the files in any other component by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getfiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

&lt;span class="c1"&gt;//=&amp;gt; ["file1", "file2"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can clear the values when we are done by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetValues&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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