<?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" version="2.0"><channel><title><![CDATA[Rachel Tomi's Blog]]></title><description><![CDATA[Hi, I'm Rachel Tomi, a front-end developer from Nigeria. On this blog, I share my thoughts and ideas on code and everything else.]]></description><link>https://tech.racheltomi.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1666174374515/JPFy1jAyB.png</url><title>Rachel Tomi&apos;s Blog</title><link>https://tech.racheltomi.com</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 11:19:52 GMT</lastBuildDate><atom:link href="https://tech.racheltomi.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[2024 Year-in-Review]]></title><description><![CDATA[At the start of this year, I sat down for my first journaling session and called it "Tabula Rasa"—a clean slate.

After stumbling through 2023 and making more mistakes than I care to admit, my intention for 2024 was simple: I wanted to re-strategize ...]]></description><link>https://tech.racheltomi.com/2024-year-in-review</link><guid isPermaLink="true">https://tech.racheltomi.com/2024-year-in-review</guid><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Tue, 31 Dec 2024 15:07:18 GMT</pubDate><content:encoded><![CDATA[<p>At the start of this year, I sat down for my first journaling session and called it "Tabula Rasa"—a clean slate.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735657514812/ee00fe5c-ee03-4103-b3ce-ec59ea4466b6.jpeg" alt class="image--center mx-auto" /></p>
<p>After stumbling through 2023 and making more mistakes than I care to admit, my intention for 2024 was simple: I wanted to re-strategize and do better. I promised myself I’d slow down, make better decisions, and stay focused on what really mattered.</p>
<p>By the end of 2023, I had landed a decent job. It seemed promising at first, but within two months, I resigned. The environment was a bit toxic, and they requested for more than I could give. So, I began the year jobless—though, thankfully, I had good savings. I had a clear plan for the year, but life has a way of surprising you.</p>
<p>In March, I unexpectedly landed a great job in a role I never planned for. It was the fastest hiring process I’ve ever experienced—two interviews and I was onboarded within three days. It felt surreal, like they had been waiting for me all along.</p>
<p>A few months in, I fell sick suddenly and was rushed to the hospital in the middle of the night. What I thought would be a quick checkup and few injections turned into an emergency surgery. I did my surgery and was in so much pain than I’ve ever been in my life. I was stuck there for about a week, but that 1 week felt like 10 years while I was on the bed. While others who had surgery at the same time were discharged, my body refused to heal and I just kept wondering, “Will I ever recover?” or “What if this pain never stops?” It was tough, really, but my family was there for me, and slowly, and with more effort than I thought I had, I began to heal. One of the things I learned this year is that;</p>
<p><em>“Growth and strength is on the other side of pain and stagnation. You won’t know how strong you are until you’ve gone through the worst. So, if you are reading this, whatever pain or disappointment you are feeling right now is only temporary and on the other side of the complete opposite - so be patient.“</em></p>
<p>From there, everything began to stabilize. I tackled my goals one by one: I moved to a new apartment, made my mum so happy, got over my fear of driving(still on this path), started a new business with my friends, bought my first car, and even got promoted as my “department lead” at work.</p>
<p>Beyond all these achievements, my biggest win was finding peace. For years, I felt unsettled, but this year, I finally felt calm and content with myself, my choices, my setbacks and how I’ve grown. It’s something I worked for, and it feels so good to finally experience it.</p>
<p>Let's not forget, I also had two wisdom teeth removed, and let me tell you—don’t do it unless you have to! The pain had me questioning my existence😭</p>
<p>Through it all, one thing remains clear: God carried me and my family. Many things happened this year I can't even write about. Every step, every breakthrough, every moment of stillness—I see His hand in all of it.</p>
<p>Was 2024 the clean slate I envisioned? In many ways, yes. But it came with lessons, growth, and a kind of peace I've always craved for.</p>
<p>Here’s to fresh starts—this journey called 'life' and the beauty of not knowing where it’ll take you. 😅</p>
]]></content:encoded></item><item><title><![CDATA[Boost Your App Performance with React Lazy and Suspense]]></title><description><![CDATA[React, as a component-based library, has many advantages, like reusability and maintainability, but also has potential disadvantages, such as unnecessary loading of unused components and large bundle size.
When building React applications, especially...]]></description><link>https://tech.racheltomi.com/boost-your-app-performance-with-react-lazy-and-suspense</link><guid isPermaLink="true">https://tech.racheltomi.com/boost-your-app-performance-with-react-lazy-and-suspense</guid><category><![CDATA[React.lazy]]></category><category><![CDATA[code splitting]]></category><category><![CDATA[React-suspense]]></category><category><![CDATA[lazy loading]]></category><category><![CDATA[react js]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Wed, 26 Jul 2023 13:59:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1690379568250/7b82de07-319b-4cd6-898d-7f5e8918db02.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>React, as a component-based library, has many advantages, like reusability and maintainability, but also has potential disadvantages, such as unnecessary loading of unused components and large bundle size.</p>
<p>When building React applications, especially complex ones, developers use a lot of media files and install third-party libraries. However, this can significantly increase the size of your application bundle, resulting in slower page load times and poor user experience. To address this issue, a good approach is to split your app bundle and implement lazy loading techniques to optimize your application performance.</p>
<p>In the past, achieving lazy loading in React required depending on third-party libraries. However, with the introduction of React.lazy() and React.Suspense in the React v16.6 update back in 2018, lazy loading has become more accessible.</p>
<p>React lazy makes it easy to code-split a React application by loading only the component and necessary bundle the user needs.</p>
<p>In this article, we will explore the implementation of React.lazy(), React.Suspense, best practices for lazy loading in React, and potential pitfalls you might encounter while working with code splitting.</p>
<h2 id="heading-what-is-lazy-loading">What is Lazy Loading?</h2>
<p>Lazy loading is a software development technique that optimizes application performance by loading specific resources only when they are needed.</p>
<p>Imagine you're building a large-scale blog using Reactjs. As your application component increases, you will notice that the initial loading time also increases, leading to slower performance. This is because all components, including those that are not immediately visible, are being loaded upfront, causing unnecessary overhead.</p>
<p>By implementing lazy loading with React Lazy, you can defer the loading of non-critical components until they are actually needed. This reduces the application’s initial loading time, optimizes performance, and provides a smoother user experience.</p>
<h2 id="heading-implementing-react-lazy-loading">Implementing React Lazy Loading</h2>
<p>To make lazy loading possible within the React library, <a target="_blank" href="https://reactjs.org/docs/code-splitting.html#reactlazy">React Lazy</a> and <a target="_blank" href="https://react.dev/reference/react/Suspense">React Suspense</a> use the power of dynamic imports and code splitting to defer codes and components until they’re needed:</p>
<p>Let’s see how we can implement lazy loading in React.</p>
<h3 id="heading-getting-started">Getting Started</h3>
<p>We'll create a basic food recipe website for demonstration.</p>
<p><strong>Prerequisites</strong></p>
<p>Before you proceed, make sure you have:</p>
<ul>
<li><p><a target="_blank" href="https://nodejs.org/en/download/"><strong>Latest Node version</strong></a> installed</p>
</li>
<li><p>A good code editor to work with. I will be using Visual code studio.</p>
</li>
</ul>
<h3 id="heading-step-1-setting-up-the-project">Step 1: Setting Up the Project</h3>
<p>To start, let's create a new React project using create-react-app:</p>
<p><code>npx create-react-app lazyloadingproject</code></p>
<p>npx allows us to use the create-react-app package without installing it first on our computer. This is especially useful if we’re working on a basic project.</p>
<p>Once the installation is complete, a folder named “lazyloadingproject” will be created in the specified directory, and all the packages you need to make the app work will be installed as well.</p>
<p>To run the project, execute:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> lazyloadingproject

npm start
</code></pre>
<p>The server will start up at <a target="_blank" href="http://localhost:3000">localhost:3000</a>, and your starting homepage will look just like the one below;</p>
<p><img src="https://imgur.com/nxqgRZA.png" alt /></p>
<p>Let's clean up the project a bit. Delete the <code>app.test.js</code> and <code>logo.svg</code> files, and remove their imports from <code>App.js</code> to prevent errors. Replace the code in <code>App.js</code> with a simple heading:</p>
<p><code>&lt;h2&gt;Lazy loading Project&lt;/h2&gt;</code></p>
<p>You should now have a clean project like this;</p>
<p><img src="https://imgur.com/zRI9cRp.png" alt /></p>
<h3 id="heading-step-2-install-react-router">Step 2: Install React Router</h3>
<p>Since we'll have multiple pages, let's install <code>react-router-dom</code> to enable smooth navigation without page refresh:</p>
<p><code>npm install react-router-dom</code></p>
<p>Once the installation is complete, the next thing is to create a components folder that houses all the components you will use throughout this project.</p>
<p>Inside this component folder, create another folder called Navbar with a navbar.js and navbar.css file and add the following code;</p>
<p><em>Navbar.js</em></p>
<pre><code class="lang-JavaScript">
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { NavLink } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Navbar.css"</span>;

<span class="hljs-keyword">const</span> Navbar = <span class="hljs-function">() =&gt;</span> {

<span class="hljs-keyword">return</span> (

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"logo-desktop"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>LazyLoading<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"nav-ul"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/recipes"</span>&gt;</span>Recipes<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/contact"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Navbar;
</code></pre>
<p><em>Navbar.css</em></p>
<pre><code class="lang-css"><span class="hljs-selector-tag">nav</span> {
<span class="hljs-attribute">display</span>: flex;
<span class="hljs-attribute">align-items</span>: center;

<span class="hljs-attribute">justify-content</span>: space-between;
<span class="hljs-attribute">background-color</span>: darkolivegreen;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.logo-desktop</span> <span class="hljs-selector-tag">p</span> {
<span class="hljs-attribute">font-weight</span>: bold;
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
<span class="hljs-attribute">color</span>: white;
}

<span class="hljs-selector-class">.nav-ul</span> {
<span class="hljs-attribute">display</span>: flex;
<span class="hljs-attribute">list-style</span>: none;
<span class="hljs-attribute">font-weight</span>: bold;
}

<span class="hljs-selector-class">.nav-ul</span> <span class="hljs-selector-tag">li</span> {
<span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> <span class="hljs-number">10px</span>;
<span class="hljs-attribute">color</span>: white;

}

<span class="hljs-selector-class">.nav-ul</span> <span class="hljs-selector-tag">li</span> <span class="hljs-selector-tag">a</span> {
<span class="hljs-attribute">color</span>: white;
}
</code></pre>
<p>Wrap your root component with <code>BrowserRouter</code> in <code>index.js</code> to enable routing:</p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">'./reportWebVitals'</span>;
<span class="hljs-keyword">import</span> { BrowserRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;
<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));
root.render(
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>Render the <code>Navbar</code> component in <code>App.js</code>:</p>
<p><em>App.js</em></p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;
<span class="hljs-keyword">import</span> Navbar <span class="hljs-keyword">from</span> <span class="hljs-string">"./Components/Navbar/Navbar"</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Navbar</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now, you have your basic navigation set up.</p>
<h3 id="heading-step-3-create-multiple-components">Step 3: Create Multiple Components</h3>
<p>Create a <code>pages</code> folder within the <code>src</code> directory and add the following files: <code>Home.js</code>, <code>Recipes.js</code>, and <code>Contact.js</code>. Populate each file with the relevant code:</p>
<p><em>Home.js</em></p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> HomeDescription <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Components/HomeDescription"</span>;
<span class="hljs-keyword">import</span> HomeImage <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Components/HomeImage"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Home.css"</span>;
<span class="hljs-keyword">const</span> Home = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">HomeDescription</span> <span class="hljs-attr">handleClick</span>=<span class="hljs-string">{handleClick}</span> <span class="hljs-attr">click</span>=<span class="hljs-string">{click}</span> /&gt;</span>
{click ? <span class="hljs-tag">&lt;<span class="hljs-name">HomeImage</span> /&gt;</span> : ""}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Home;
</code></pre>
<p><em>Home.css</em></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.flex</span> {
<span class="hljs-attribute">display</span>: flex;
<span class="hljs-attribute">align-items</span>: center;
<span class="hljs-attribute">flex-direction</span>: column;
}
<span class="hljs-selector-class">.imgclass</span> {
<span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
<span class="hljs-attribute">height</span>: <span class="hljs-number">30%</span>;
<span class="hljs-attribute">object-fit</span>: cover;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">50px</span> <span class="hljs-number">0</span>;
}
<span class="hljs-selector-class">.flex</span> <span class="hljs-selector-tag">h1</span> {
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}
<span class="hljs-selector-class">.flex</span> <span class="hljs-selector-tag">p</span> {
<span class="hljs-attribute">width</span>: <span class="hljs-number">60%</span>;
}
<span class="hljs-selector-class">.recipe-btn</span> {
<span class="hljs-attribute">padding</span>: <span class="hljs-number">14px</span> <span class="hljs-number">8px</span>;
<span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;
<span class="hljs-attribute">background-color</span>: darkolivegreen;
<span class="hljs-attribute">color</span>: white;
<span class="hljs-attribute">font-weight</span>: bold;
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">1rem</span>;
<span class="hljs-attribute">cursor</span>: pointer;
<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">7px</span>;
<span class="hljs-attribute">border</span>: none;
}
</code></pre>
<p>In the "Home.js" component, two different components are rendered on the home page: HomeDescription and HomeImage. To set up these components, create two new files called "HomeDescription.js" and "HomeImage.js" and paste the corresponding code.</p>
<p><em>HomeDescription.js</em></p>
<pre><code class="lang-JavaScript">
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"../Pages/Home/Home.css"</span>;
<span class="hljs-keyword">const</span> HomeDescription = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">let</span> navigate = useNavigate();
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Tomi's Recipe App<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab
illo inventore veritatis et quasi architecto beatae{" "}
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recipe-btn"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> navigate("/recipes")}&gt;
Check Recipes
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> HomeDescription;
</code></pre>
<p><em>HomeImage.js</em></p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { format } <span class="hljs-keyword">from</span> <span class="hljs-string">"date-fns"</span>;
<span class="hljs-keyword">import</span> img3 <span class="hljs-keyword">from</span> <span class="hljs-string">"../Assets/img3.jpg"</span>;
<span class="hljs-keyword">const</span> HomeImage = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">let</span> today = format(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-string">"MM/dd/yyyy"</span>);
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>.
<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{today}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"imgclass"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{img3}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"homeimage"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> HomeImage;
</code></pre>
<p>Notice that the date-fns library is used to format the current application date. Be sure to install it:</p>
<p><code>npm install date-fns</code></p>
<p>For the other pages, follow similar steps and paste the corresponding code.</p>
<p><em>Recipes.js</em></p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> img1 <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Assets/img1.jpg"</span>;
<span class="hljs-keyword">import</span> img2 <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Assets/img2.jpg"</span>;
<span class="hljs-keyword">import</span> img3 <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Assets/img3.jpg"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Recipes.css"</span>;
<span class="hljs-keyword">const</span> Recipes = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recipewrapper"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"recipeheading"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Recipes<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"wrapper"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{img1}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"imgclass"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"img 1"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae{" "}
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{img2}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"imgclass"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"img 1"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae{" "}
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{img3}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"imgclass"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"img 1"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae{" "}
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span></span>
);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Recipes;
</code></pre>
<p><em>Recipes.css</em></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.recipewrapper</span> {
<span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span> <span class="hljs-number">0</span>;
}
<span class="hljs-selector-class">.recipeheading</span> <span class="hljs-selector-tag">h1</span> {
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}
<span class="hljs-selector-class">.imgclass</span> {
<span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
<span class="hljs-attribute">height</span>: <span class="hljs-number">60%</span>;
<span class="hljs-attribute">object-fit</span>: cover;
}
<span class="hljs-selector-class">.wrapper</span> {
<span class="hljs-attribute">display</span>: flex;
}
<span class="hljs-selector-class">.card</span> {
<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">20px</span>;
}
</code></pre>
<p><em>Contact.js</em></p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Contact.css"</span>;
<span class="hljs-keyword">const</span> Contact = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-page"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Contact Us<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-card"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Name<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">"name"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-input"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email<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">"email"</span>
<span class="hljs-attr">className</span>=<span class="hljs-string">"contact-input"</span>
<span class="hljs-attr">placeholder</span>=<span class="hljs-string">"test@example.com"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</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> <span class="hljs-attr">className</span>=<span class="hljs-string">"contact-btn"</span>&gt;</span>
Submit
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span></span>
);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Contact;
</code></pre>
<p><em>Contact.css</em></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.contact-page</span> <span class="hljs-selector-tag">h2</span> {
<span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}
<span class="hljs-selector-class">.contact-card</span> {
<span class="hljs-attribute">display</span>: flex;
<span class="hljs-attribute">flex-direction</span>: column;
<span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">239</span>, <span class="hljs-number">239</span>, <span class="hljs-number">239</span>);
<span class="hljs-attribute">width</span>: <span class="hljs-number">26%</span>;
<span class="hljs-attribute">max-height</span>: <span class="hljs-number">480px</span>;
<span class="hljs-attribute">margin</span>: <span class="hljs-number">0px</span> auto;
<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0</span>;
}
<span class="hljs-selector-class">.contact-input</span> {
<span class="hljs-attribute">width</span>: <span class="hljs-number">90%</span>;
<span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span>;
<span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#808080</span>;
}
<span class="hljs-selector-tag">label</span> {
<span class="hljs-attribute">text-align</span>: left;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span>;
<span class="hljs-attribute">font-weight</span>: bold;
}
<span class="hljs-selector-class">.contact-btn</span> {
<span class="hljs-attribute">border</span>: none;
<span class="hljs-attribute">background-color</span>: darkolivegreen;
<span class="hljs-attribute">color</span>: white;
<span class="hljs-attribute">font-weight</span>: bold;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">6px</span> <span class="hljs-number">14px</span>;
<span class="hljs-attribute">transition</span>: all <span class="hljs-number">0.4s</span> ease-in;
<span class="hljs-attribute">cursor</span>: pointer
</code></pre>
<p>The recipe page contains more details about some recipes and their descriptions. The final page, which is the contact page, contains a basic HTML contact form.</p>
<h3 id="heading-step-4-define-routes">Step 4: Define Routes</h3>
<p>Since the App component serves as the root for this project, let's set up the routes within it:</p>
<pre><code class="lang-JavaScript">
&lt;div className=<span class="hljs-string">"App"</span>&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/recipes"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Recipes</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/contact"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Contact</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span></span>
&lt;/div&gt;
…
</code></pre>
<p>We imported the Routes and Route feature from react-router-dom, defined our routes with paths, and linked them to their respective components.</p>
<p>This is what your home page looks like now.</p>
<p><img src="https://imgur.com/Ff4vOKf.png" alt /></p>
<p>Now, open the DevTools and click on the network tab.</p>
<p>In the "bundle.js" tab, you'll notice that the two components on the homepage are bundled together. The app's size and loading time are currently <strong>445kb</strong> and <strong>174ms</strong>, respectively.</p>
<p><img src="https://imgur.com/7Npo8Co.png" alt /></p>
<p>This is because React downloads all required resources during the initial app load, which isn't optimal for performance.</p>
<p>To enhance performance, you can split your app's components and bundle only the necessary resources for each load.</p>
<h2 id="heading-implementing-lazy-loading-using-reactlazy-and-reactsuspense">Implementing Lazy Loading Using React.Lazy and React.Suspense</h2>
<p>For our project, we'll utilize the React.lazy() function to load resources as needed and fetch additional JavaScript as users navigate between pages.</p>
<p>Now, let's refactor the imports in your Home.js file as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> HomeDescription = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"../../Components/HomeDescription"</span>));

<span class="hljs-keyword">const</span> HomeImage = React.lazy(<span class="hljs-function">() =&gt;</span> (<span class="hljs-string">"../../Components/HomeImage"</span>));
</code></pre>
<p>If you reload your app and navigate to other pages, you will get the error below.</p>
<p><img src="https://imgur.com/f1GjcPl.png" alt /></p>
<p>This error occurs because React.lazy requires the Suspense component to display fallback content while the lazy component loads.</p>
<h3 id="heading-react-suspense">React Suspense</h3>
<p>Suspense is a component required by the lazy() function to reflect some fallback content while the lazy component loads.</p>
<p>To address this error, wrap the Suspense component around the multiple lazy components in</p>
<pre><code class="lang-javascript">…
&lt;div className=<span class="hljs-string">"flex"</span>&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">HomeDescription</span> <span class="hljs-attr">handleClick</span>=<span class="hljs-string">{handleClick}</span> <span class="hljs-attr">click</span>=<span class="hljs-string">{click}</span> /&gt;</span>
{click ? <span class="hljs-tag">&lt;<span class="hljs-name">HomeImage</span> /&gt;</span> : ""}
<span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>Reload your browser, and in the network tab, click on bundle.js again.</p>
<p><img src="https://imgur.com/LdTjMJw.png" alt /></p>
<p>You'll notice that the app's size has decreased significantly to 302B, and the loading time is now 19ms. The app's components have also been split into two, and the HomeImage component only loads when the "Check Recipes" button is clicked.</p>
<h2 id="heading-what-are-some-best-practices-when-it-comes-to-react-lazy-loading">What are some best practices when it comes to react lazy loading?</h2>
<p>While our application's performance has improved considerably, lazy loading components can potentially negatively impact the overall website experience with UI glitches, excessive network requests, and multiple chunk files.</p>
<p>To create evenly-sized bundles without disrupting the user experience, you can employ route-based code splitting.</p>
<h3 id="heading-route-based-code-splitting">Route Based Code-Splitting</h3>
<p>Route-based code splitting involves code splitting only the components rendered when a specific URL is visited.</p>
<p>To achieve this, conditionally load your routes in the App.js file using React.lazy(). This ensures that resources for these routes are loaded only when the route is accessed.</p>
<p>In the App.js file, refactor the imported components to use React.lazy():</p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">const</span> Contact = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./Pages/Contacts/Contact"</span>));
<span class="hljs-keyword">const</span> Home = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./Pages/Home/Home"</span>));
<span class="hljs-keyword">const</span> Recipes = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./Pages/Recipes/Recipes"</span>));
</code></pre>
<p>Next, use the Suspense component and wrap the Routes within it:</p>
<pre><code class="lang-javascript">&lt;div className=<span class="hljs-string">"App"</span>&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>}&gt;
<span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/recipes"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Recipes</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/contact"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Contact</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>After reloading your recipe application again and checking the network tab, you will see that a <em>“</em><code>src_Pages_Home_Home_js.chunk.js</code><em>”</em> file gets added to the tab. This is the JavaScript code of the Home page, which gets split from the bundle.js file and added to a separate chunk.js file. Similarly, as you load other components, additional chunk.js files are created for each lazily loaded component.</p>
<h3 id="heading-preloading">Preloading</h3>
<p>To mitigate potential UI glitches stemming from lazy loading, you can preload components or load them ahead of time. The react-lazy-with-preload library streamlines this process.</p>
<p><strong>Install the library:</strong></p>
<p><code>npm install react-lazy-with-preload</code></p>
<p>Change your import statement from this;</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> HomeImage = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"../../Components/HomeImage"</span>));
</code></pre>
<p>To this;</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { lazyWithPreload } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-lazy-with-preload"</span>;

<span class="hljs-keyword">const</span> HomeImage = lazyWithPreload(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./OtherComponent"</span>));
</code></pre>
<p>And finally,</p>
<p>use the preload method like this;</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
HomeImage.preload();
}, [])
</code></pre>
<p>If you reload the app again, you will notice that your HomeImage component now loads immediately without having to click the “check recipes” button.</p>
<p><img src="https://imgur.com/BqWUkgM.png" alt /></p>
<h3 id="heading-named-export-in-reactlazy">Named Export in React.Lazy</h3>
<p>Suppose you currently use named exports in your React components. In that case, you might need to re-export these named exports as default exports in an intermediate module to prevent unused components from being imported. This is because React.Lazy() currently doesn’t support named exports.</p>
<p>For instance, if you have the following named export:</p>
<p><code>export const namedComponent = "../../Components/HomeDescription";</code></p>
<p>You can re-export it as a default component like so;</p>
<p><code>export {namedComponent as default} from "../../Components/HomeDescription";</code></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article has demonstrated how to implement the lazy function and Suspense component in React applications to enhance performance. You've also learned about the downsides of React lazy loading and how to address them using route-based splitting and preloading. Lastly, you learned about the best practices for React lazy loading.</p>
<p>You can check out the full code here: <a target="_blank" href="https://github.com/Racheal-spec/reactlazy">https://github.com/Racheal-spec/reactlazy</a>  </p>
<p>Thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[5 Ways to Improve Your Application Performance Monitoring]]></title><description><![CDATA[The world and technology keep evolving. Over time, applications with functions ranging from buying and selling online to holding meetings to keeping up with friends and family have progressed. Now, we are able to automate actions that used to be manu...]]></description><link>https://tech.racheltomi.com/5-ways-to-improve-your-application-performance-monitoring</link><guid isPermaLink="true">https://tech.racheltomi.com/5-ways-to-improve-your-application-performance-monitoring</guid><category><![CDATA[Performance Optimization]]></category><category><![CDATA[performance]]></category><category><![CDATA[monitoring tool]]></category><category><![CDATA[mo]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Wed, 03 May 2023 07:29:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683098338501/3a670326-d9a9-4d01-8670-6f667d712b61.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The world and technology keep evolving. Over time, applications with functions ranging from buying and selling online to holding meetings to keeping up with friends and family have progressed. Now, we are able to automate actions that used to be manual or at least perform them in the most efficient way possible. This automation is made possible through the use of our applications. Now imagine one of these applications stops working for just 10 minutes. Actually, we don't have to imagine since it's happened.<br />Back in 2013, Amazon had 15 minutes of downtime. <a target="_blank" href="https://smallbiztrends.com/2013/08/amazon-down-custom-error-page.html">According to Small Business Trends</a>, Forbes calculated that the downtime cost Amazon about $66,240 per minute. Now, that’s a lot to lose in just one minute.<br />As you can see, it's essential that our applications perform well. To prevent downtimes like the one Amazon experienced and other breaks from happening, it’s important to pay close attention to how you're managing your application's performance. In this post, I'll define application performance monitoring and give you tips on how to make the most of your monitoring tools. But before we talk about application performance monitoring, let's understand what makes an application high performing.</p>
<h2 id="heading-how-do-we-judge-an-applications-performance">How Do We Judge an Application's Performance?</h2>
<p>Application performance entails how well an application functions and how seamless the user experience is. This includes how simple it is for users to navigate through your app and receive desired responses and behaviour. Therefore, If an application is fast, predictable, and stable, you can consider it high performing.<br />Now, how do you ensure that your application is never low on performance or experiences downtime? This is where application performance monitoring comes in.</p>
<h2 id="heading-what-is-application-performance-monitoring-apm">What Is Application Performance Monitoring (APM)?</h2>
<p>Application performance monitoring involves businesses using monitoring tools or software to track their applications. Organizations use these monitoring tools to get visibility into the performance metrics of their applications such as response time, errors, memory, latency, and so on. Monitoring your application helps to quickly track down the underlying cause of problems or bugs in your apps as well as provide solutions to solve these issues before they affect users’ experience.<br />Since we already have a basic understanding of what application performance monitoring is, it’s time to focus on how to improve your application performance monitoring to drive better results.</p>
<h2 id="heading-how-do-you-improve-your-application-performance-monitoring">How Do You Improve Your Application Performance Monitoring?</h2>
<p>There are five simple steps you can take to improve your application performance monitoring.</p>
<h3 id="heading-1-choose-the-right-monitoring-software">1. Choose the Right Monitoring Software</h3>
<p>Modern applications are complex, so it's often difficult for development teams to manually figure out what's causing performance problems. So, instead, they commonly turn to an application performance monitoring tool.<br />Choosing the right monitoring tool can be a hassle, as several application performance monitoring solutions exist, each with unique features. How, then, do you identify the right application performance monitoring solution for your business?<br />Be sure to employ an application performance monitoring solution that</p>
<ul>
<li><p>is easy to use,</p>
</li>
<li><p>transforms data into a useful solution,</p>
</li>
<li><p>provides complete visibility into the whole application stack, and</p>
</li>
<li><p>provides a more actionable view of performance issues.</p>
</li>
</ul>
<p>To make your decision-making process even easier, an application performance monitoring tool such as <a target="_blank" href="https://www.netreo.com/">Netreo</a> provides useful insights into performance after analysis, full-stack monitoring, real-time dashboards, and a great user experience. In this way, you get to focus on what’s important in your business while Netreo handles your application performance smartly.</p>
<h3 id="heading-2-create-your-own-rules">2. Create Your Own Rules</h3>
<p>Every organization has an approach or strategy that’s unique to them when monitoring performance. As a result, it's critical to ensure that your application performance monitoring solution addresses the difficulties or challenges that your company is encountering.<br />You can do this by creating custom rules that define the requirements your application must meet. That way, when your app fails to meet a requirement, your application performance monitoring tool will create an issue that such a problem exists. These custom rules can include what you believe to be typical app behaviour for metrics such as the average response rate, CPU usage, error rates, and so on.<br />For example, you can decide to create a rule that when an API call takes longer than 1,500 milliseconds, your application performance monitoring solution should flag the issue. This way, you will only get an alert when your application has met this condition.</p>
<h3 id="heading-3-use-a-system-that-provides-real-time-notifications">3. Use a System that Provides Real-Time Notifications</h3>
<p>To immediately resolve performance issues before they become critical, it’s important to have access to a full-stack alerting system in your application. This system sends a notification to the expected individual as soon as your key metrics begin to change. An alert might not necessarily mean that a problem has occurred; it might also be a warning for problems that might occur in the future. This way, you can quickly attend to issues before they become complex.<br />It gets even better with <a target="_blank" href="https://www.netreo.com/platform/intelligent-alerts-management/">Netreo’s intelligent alert management system</a>. This system doesn’t just handle changes in your application environment smartly; it also helps validate alerts automatically through multiple tests to get rid of several false alarms that might flood your phone or email.</p>
<h3 id="heading-4-build-a-special-team">4. Build a Special Team</h3>
<p>To proactively attend to your application performance issues as they arise, it’s important to have a special engineering team that helps resolve these performance problems as they’re discovered. This team will be in charge of monitoring the performance of applications in the company, ranging from slow servers and loading time to traffic spikes and user experience.<br />But to create your application performance monitoring solution's rules, set up notifications, and build a team, you first have to be getting the right information. This leads us to the last point: using the right metrics.</p>
<h3 id="heading-5-use-the-appropriate-metrics">5. Use the Appropriate Metrics</h3>
<p>With application performance monitoring, businesses can track the different aspects of their applications in real-time. However, it's usually difficult to get the root cause of these application performance problems due to inappropriate analysis methods.<br />To ensure that an application's performance is reliable, developers must make use of the appropriate procedures and metrics to discover the exact source of a problem. You should monitor important metrics such as</p>
<ul>
<li><p>memory usage,</p>
</li>
<li><p>request rates,</p>
</li>
<li><p>CPU usage, and</p>
</li>
<li><p>response time.</p>
</li>
</ul>
<p>But you shouldn't assume that because your request rates, for example, are high that your application is high performing. You should always view these important metrics from a larger perspective in an application environment rather than in isolation.</p>
<h3 id="heading-key-metrics-to-measure">Key Metrics to Measure</h3>
<p>Let's take a quick look at some key metrics you should focus on.</p>
<h4 id="heading-request-rates">Request Rates</h4>
<p>This metric helps you to keep track of how many requests your application receives, where they come from, and the number of returning users. Monitoring request rates also gives you a decent idea of how much traffic comes into your app. This helps you understand how this increase or decrease in traffic can affect your organization's success.</p>
<h4 id="heading-response-time">Response Time</h4>
<p>Response time is the time between when a user submits a request and when the program shows that the request is complete. The result from this metric usually indicates whether speed affects your application performance.</p>
<h4 id="heading-error-rates">Error Rates</h4>
<p>This is the number of requests that result in an error when users make requests within an application. This metric is very important in determining how efficient an application is. This is because it measures how often an application's performance fails.</p>
<h4 id="heading-cpu-and-memory-usage">CPU and Memory Usage</h4>
<p>You can check how much CPU and memory your application is consuming in real time by analyzing your CPU and memory usage. This enables developers to swiftly resolve problems on your server as soon as they occur. An application that has a high memory or CPU usage will perform poorly regardless of how low the site traffic is.</p>
<h4 id="heading-latency">Latency</h4>
<p>Latency is the time it takes for a block of data to be sent over a network. For example, if it takes 100 milliseconds for a request to be sent over from the client to the server, then the latency of such an application is 100 milliseconds. An increase in latency might indicate a performance issue within an application. This is because latency determines the speed with which an application responds to a request.</p>
<h2 id="heading-focus-on-whats-most-important">Focus on What’s Most Important</h2>
<p>To understand your users' experience, it’s important to view your application from the users’ perspective. What is the average response rate for the app? How often do users come back? Do they get an error when a particular user action is being executed? If yes, what are the errors? How many users were impacted, and on what devices?<br />All of these and more are questions that must be answered when monitoring your application's performance. However, using an application performance monitoring tool and adhering to the rules above can give your organization an edge. You get to focus on what matters while these application performance monitoring solutions intelligently do the monitoring for you.</p>
<p><em>This post is originally published on</em> <a target="_blank" href="https://www.netreo.com/blog/improve-application-performance-monitoring/"><em>Netreo</em></a></p>
]]></content:encoded></item><item><title><![CDATA[How to Embed Amazon Quick-Sight Dashboard for Registered Users into Your React Application]]></title><description><![CDATA[One of the most fascinating things about using different products or services these days is the ability of businesses to gather data, analyze it and make decisions that deliver personalized services and improve your experiences. Making decisions is a...]]></description><link>https://tech.racheltomi.com/how-to-embed-amazon-quick-sight-dashboard-for-registered-users-into-your-react-application</link><guid isPermaLink="true">https://tech.racheltomi.com/how-to-embed-amazon-quick-sight-dashboard-for-registered-users-into-your-react-application</guid><category><![CDATA[#Amazon QuickSight]]></category><category><![CDATA[AWS]]></category><category><![CDATA[React]]></category><category><![CDATA[aws quicksight]]></category><category><![CDATA[#cloud #Amazon QuickSight #Data Visualization #AWS #Business Intelligence #Analytics #Cloud Computing #Data Analysis #Data Insights #Data Visualization Tools #Amazon S3 #Dashboards #Charts and Graphs #Data Sets]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Sun, 15 Jan 2023 23:00:00 GMT</pubDate><content:encoded><![CDATA[<p>One of the most fascinating things about using different products or services these days is the ability of businesses to gather data, analyze it and make decisions that deliver personalized services and improve your experiences. Making decisions is an integral part of running a business. And to make the best one for you, having access to the right information at the right time and in the right format is crucial for any organization. This is why Amazon Quick Sight exists.</p>
<h2 id="heading-what-is-amazon-quicksight">What is Amazon Quicksight?</h2>
<p>Amazon quick sight is a cloud-based, faster, and easy-to-use business intelligence service that allows organizations to collect data, analyze and turn them into useful insights by creating data visualizations and dashboards for their users and employees. It can connect to different data sources in the cloud, such as spreadsheets, big data sources, third-party databases, and so on. It then transforms this data into beautiful, sophisticated interactive dashboards, hereby giving you and your users the ability to analyze information fast.</p>
<p>One of Quick Sight’s most beautiful features is the ability to access data from anywhere, i.e., it can be embedded into your applications and accessed from your websites, mobile devices and even email. Amazon quick-sight dashboards can be embedded into internal applications in two ways;</p>
<p>• <strong>For Anonymous users</strong></p>
<p>Anonymous users are individuals who do not have an account or login credentials to access the Quicksight dashboard. They can view the dashboard, but their access might be limited depending on how the dashboard is configured. Anonymous access can be useful for sharing information with a broad audience, such as customers, partners, or the general public.</p>
<p>• <strong>For registered users</strong></p>
<p>Registered users, on the other hand, are individuals who have an account and login credentials to access the Quicksight dashboard. They can view the full dashboard and interact with its features, including filtering data, drilling down into specific metrics, and creating custom visualizations. Registered access is typically reserved for employees, authorized partners, or other individuals who require more advanced data access.</p>
<p>This article will focus on embedding a quick-sight dashboard for registered users into your React application.</p>
<h2 id="heading-steps-in-embedding-a-quick-sight-dashboard-into-a-react-application">Steps in Embedding a Quick Sight Dashboard into a React Application</h2>
<p>To successfully embed a quick sight dashboard into your web application, you must meet the following requirements;</p>
<p><strong>Requirements</strong></p>
<p>• Have a good understanding of JavaScript/ReactJs.</p>
<p>• Subscribed to Amazon Quick Sight Enterprise Edition.</p>
<p>• You have analyses/visualizations published into one or more dashboards.</p>
<p>• You have admin rights on quick sight.</p>
<h3 id="heading-step-1-verify-your-users-access-to-the-dashboard">Step 1: Verify Your User’s Access to the Dashboard</h3>
<p>As a developer, you will most likely work in a team and might not be the original owner of the quick-sight account you will be using. So, even if you have been granted admin rights, you will still not have permission to view the dashboard you want to embed and might get an error that looks like the one below.</p>
<p><img src="https://imgur.com/KqCObcT.png" alt /></p>
<p>The only solution to this is that the admin shares the dashboard that needs to be embedded with your user. To grant a user permission to view a dashboard, the admin will need to click on the share icon at the top right corner of the dashboard.</p>
<p><img src="https://imgur.com/kZgbEVZ.png" alt /></p>
<p>Click on “share dashboard,” Input the user’s email and click the share button. The user will get an email like the one below and now have permission to view, share, and export the dashboard.</p>
<p><img src="https://imgur.com/VPczNAp.png" alt /></p>
<h3 id="heading-step-2-copy-your-dashboard-id-and-whitelist-your-website-domain">Step 2: Copy your Dashboard Id and Whitelist your Website Domain</h3>
<p>After the dashboard has been shared with the required user, the next step is to copy the dashboard Id from the dashboard URL and save it in a notepad, as shown below.</p>
<p><img src="https://imgur.com/VlUY32L.png" alt /></p>
<p>To whitelist the domain, click on the <strong><em>profile icon &gt; manage quicksight&gt; Domains and Embedding</em></strong>. Enter the domain names (including localhost domains) and add them to the list of embedded URLs. Embedded dashboards only work on domains that have been allowed.</p>
<h3 id="heading-step-3-set-up-permissions-for-the-webserver">Step 3: Set Up Permissions for the Webserver</h3>
<p>If you’re embedding a dashboard into your app, your users will have to assume a role that gives them access to Amazon quick sight and the dashboard. If permissions are set correctly, a new dashboard URL with a unique auth code is generated for every login, and users will no longer have to log into quick sight to view dashboards. To achieve this, you must create an AWS Identity and Access Management (IAM) role that allows users to become a reader on Amazon Quicksight and retrieve embedding URLs for a unique user pool.</p>
<p>Click the “Create role” button on the roles page and choose the “Web identity” option. You will be prompted to include your identity pool Id.</p>
<p><img src="https://imgur.com/KpclGQi.png" alt /></p>
<p>If you do not have an Identity Pool ID, go to Amazon Cognito, create a user pool first, and then create the identity pool.</p>
<p><img src="https://imgur.com/kaOvXXb.png" alt /></p>
<p>Include the identity pool ID and click “Next” to create a new policy.</p>
<p>This is what a sample policy looks like;</p>
<pre><code class="lang-JSON">{ {
  <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>: [
      {
      <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"quicksight:RegisterUser"</span>,
      <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"*"</span>,
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>
      },
      {
      <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
      <span class="hljs-attr">"Action"</span>: [
          <span class="hljs-string">"quicksight:GenerateEmbedUrlForRegisteredUser"</span>
      ],
      <span class="hljs-attr">"Resource"</span>: “*”
      },
      <span class="hljs-string">"Action"</span>: <span class="hljs-string">"sts:AssumeRole"</span>,
      <span class="hljs-string">"Resource"</span>: <span class="hljs-string">"*"</span>,
      <span class="hljs-string">"Effect"</span>: <span class="hljs-string">"Allow"</span>
  }
  ]
}
</code></pre>
<p>Assign this policy to the AuthRole created earlier. Leave tags empty, review the role, and click <strong>“create policy.”</strong></p>
<p>This policy allows you to create a role that permits you to register a user and assume the role that allows you to generate a dashboard URL using the GenerateEmbedUrlForRegisteredUser() method</p>
<h3 id="heading-step-4-generate-the-dashboard-url">Step 4: Generate the dashboard URL</h3>
<p>To generate a unique dashboard URL every time a user authenticates, performing the below steps in your web server is essential.</p>
<p>• The first step is to</p>
<p>For a user to be permitted to view a quick-sight dashboard, such a user has to be authenticated using Cognito.</p>
<p><strong>How does it work?</strong></p>
<p>Cognito generates three token IDs every time a user logs into your application. These IDs are IDToken, RefreshToken and AccessToken. These tokens are sent to your application server each time a user tries to authenticate or use any AWS service that requires authentication. This same token is what we will be using for every unique user that needs to view your Quicksight dashboard.</p>
<p>• The next step is to create a temporary IAM user and call the <strong><em>“sts.assume role method”</em></strong> to generate the IAM credentials.</p>
<p>Your application assumes this IAM role on the user's behalf and adds the user to Quicksight.</p>
<p>• Next, register the user in Quicksight with the temporary credentials using the “quicksight.registerUser” method.</p>
<p>This allows a user to become a registered user in the Amazon Quicksight account and also retrieve the requested dashboard URL.</p>
<p>• Generate the embedded URL</p>
<p>This step can only be done on the web server, and this is what a sample JavaScript code from Quicksight documentation looks like;</p>
<pre><code class="lang-JavaScript">   <span class="hljs-keyword">const</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-sdk'</span>);

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateEmbedUrlForRegisteredUser</span>(<span class="hljs-params">
        accountId,
        dashboardId,
        openIdToken, <span class="hljs-regexp">//</span> Cognito-based token
        userArn, <span class="hljs-regexp">//</span> registered user arn
        roleArn, <span class="hljs-regexp">//</span> IAM user role to use for embedding
        sessionName, <span class="hljs-regexp">//</span> Session name for the roleArn assume role
        allowedDomains, <span class="hljs-regexp">//</span> Runtime allowed domain for embedding
        getEmbedUrlCallback, <span class="hljs-regexp">//</span> GetEmbedUrl success callback method
        errorCallback <span class="hljs-regexp">//</span> GetEmbedUrl error callback method
        </span>) </span>{
        <span class="hljs-keyword">const</span> stsClient = <span class="hljs-keyword">new</span> AWS.STS();
        <span class="hljs-keyword">let</span> stsParams = {
            <span class="hljs-attr">RoleSessionName</span>: sessionName,
            <span class="hljs-attr">WebIdentityToken</span>: openIdToken,
            <span class="hljs-attr">RoleArn</span>: roleArn
        }
        stsClient.assumeRoleWithWebIdentity(stsParams, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>) </span>{
            <span class="hljs-keyword">if</span> (err) {
                <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Error assuming role'</span>);
                <span class="hljs-built_in">console</span>.log(err, err.stack);
                errorCallback(err);
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">const</span> getDashboardParams = {
                    <span class="hljs-string">"AwsAccountId"</span>: accountId,
                    <span class="hljs-string">"ExperienceConfiguration"</span>: {
                        <span class="hljs-string">"Dashboard"</span>: {
                            <span class="hljs-string">"InitialDashboardId"</span>: dashboardId
                        }
                    },
                    <span class="hljs-string">"UserArn"</span>: userArn,
                    <span class="hljs-string">"AllowedDomains"</span>: allowedDomains,
                    <span class="hljs-string">"SessionLifetimeInMinutes"</span>: <span class="hljs-number">600</span>
                };

                <span class="hljs-keyword">const</span> quicksightClient = <span class="hljs-keyword">new</span> AWS.QuickSight({
                    <span class="hljs-attr">region</span>: process.env.AWS_REGION,
                    <span class="hljs-attr">credentials</span>: {
                        <span class="hljs-attr">accessKeyId</span>: data.Credentials.AccessKeyId,
                        <span class="hljs-attr">secretAccessKey</span>: data.Credentials.SecretAccessKey,
                        <span class="hljs-attr">sessionToken</span>: data.Credentials.SessionToken,
                        <span class="hljs-attr">expiration</span>: data.Credentials.Expiration
                    }
                });
                <span class="hljs-keyword">var</span> params = {
   <span class="hljs-attr">AwsAccountId</span>: “account id”,
   <span class="hljs-attr">Email</span>: <span class="hljs-string">'email'</span>,
   <span class="hljs-attr">IdentityType</span>: <span class="hljs-string">'IAM'</span> ,
   <span class="hljs-attr">Namespace</span>: <span class="hljs-string">'default'</span>,
   <span class="hljs-attr">UserRole</span>: ADMIN | AUTHOR | READER | RESTRICTED_AUTHOR | RESTRICTED_READER,
   <span class="hljs-attr">IamArn</span>: <span class="hljs-string">'Cognito Identity role arn'</span>,
   <span class="hljs-attr">SessionName</span>: <span class="hljs-string">'session name given in the assume role creation'</span>,
};
quicksight.registerUser(params, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, data1</span>) </span>{
   <span class="hljs-keyword">if</span> (err) <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"err register user”); 
   // an error occurred
   else {
      // console.log("</span>Register User1”);
   }
})

                quicksightClient.generateEmbedUrlForRegisteredUser(getDashboardParams, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>) </span>{
                    <span class="hljs-keyword">if</span> (err) {
                        <span class="hljs-built_in">console</span>.log(err, err.stack);
                        errorCallback(err);
                    } <span class="hljs-keyword">else</span> {
                        <span class="hljs-keyword">const</span> result = {
                            <span class="hljs-string">"statusCode"</span>: <span class="hljs-number">200</span>,
                            <span class="hljs-string">"headers"</span>: {
                                <span class="hljs-string">"Access-Control-Allow-Origin"</span>: <span class="hljs-string">"*"</span>, <span class="hljs-comment">// Use your website domain to secure access to GetEmbedUrl API</span>
                                <span class="hljs-string">"Access-Control-Allow-Headers"</span>: <span class="hljs-string">"Content-Type"</span>
                            },
                            <span class="hljs-string">"body"</span>: <span class="hljs-built_in">JSON</span>.stringify(data),
                            <span class="hljs-string">"isBase64Encoded"</span>: <span class="hljs-literal">false</span>
                        }
                        getEmbedUrlCallback(result);
                    }
                });
            }
        });
    }
</code></pre>
<h3 id="heading-step-5-embed-url-into-react-app">Step 5: Embed URL into React App</h3>
<p>Once the URL has been generated, you will get a response like the one below;</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//The URL returned is over 900 characters. For this example, we've shortened the string for</span>
<span class="hljs-comment">//readability and added ellipsis to indicate that it's incomplete.</span>
    {
        <span class="hljs-string">"Status"</span>: <span class="hljs-string">"200"</span>,
        <span class="hljs-string">"EmbedUrl"</span>: <span class="hljs-string">"https://quicksightdomain/embed/12345/dashboards/67890..."</span>,
        <span class="hljs-string">"RequestId"</span>: <span class="hljs-string">"7bee030e-f191-45c4-97fe-d9faf0e03713"</span>
    }
</code></pre>
<p>Usually, all you would need to embed this in your app is by adding the "EmbedUrl" in an iframe. But since we are embedding this in a react application, we will need a more consistent URL that will not timeout.</p>
<p>To embed the URL into your React App, you will need to create an endpoint that returns this "EmbedUrl" from the backend or application server.</p>
<p>Once the URL has been created on the backend, we should now have an endpoint that includes the dashboard Id and takes in a unique email as an argument. This endpoint might look something like this;</p>
<p><code>https://samplequicksighturl.com/embedurlquicksight/get?dashboard_id=2b8560-b43216-00985j-67h90-eb369&amp;email=${email}</code>;</p>
<p>To get the quick-sight embed URL that we need on the front end;</p>
<p>first, we will need to install Axios using npm;</p>
<p><code>npm install axios</code></p>
<p>Next, create a <strong>src/EmbedUrl.js</strong> file and include the following lines.</p>
<pre><code class="lang-JavaScript">Import React, { useEffect, useState } <span class="hljs-keyword">from</span> “react”;
Import axios <span class="hljs-keyword">from</span> “axios”;
<span class="hljs-keyword">import</span> { Auth } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-amplify'</span>;

<span class="hljs-keyword">let</span> QuickSightEmbedding = <span class="hljs-built_in">require</span>(<span class="hljs-string">'amazon-quicksight-embedding-sdk'</span>);
<span class="hljs-keyword">const</span> EmbedDashboard = <span class="hljs-function">() =&gt;</span> {
Const baseUrl = https:<span class="hljs-comment">//sampleurl.com;</span>
Const [qsUrl, setUrl] = useState(“”);

<span class="hljs-keyword">const</span> getQsdb = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">let</span> user = <span class="hljs-keyword">await</span> Auth.currentSession();
    <span class="hljs-keyword">const</span> payloadsub = user.getIdToken().payload.sub;
    <span class="hljs-keyword">const</span> email = user.getIdToken().payload.email;
    <span class="hljs-keyword">const</span> options = {
      <span class="hljs-attr">response</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">queryStringParameters</span>: {
        <span class="hljs-attr">jwtToken</span>: user.getIdToken().getJwtToken(),
        <span class="hljs-attr">payloadSub</span>: payloadsub,
        <span class="hljs-attr">email</span>: email
      }
    };
    <span class="hljs-keyword">let</span> api = <span class="hljs-keyword">await</span> axios.get(
      <span class="hljs-string">`<span class="hljs-subst">${baseUrl}</span>?embedurlquicksight/get?dashboard_id=2b8560-b43216-00985j-67h90-    eb369&amp;email=<span class="hljs-subst">${email}</span>`</span>,
      user.getIdToken().getJwtToken(),
      options
    );
   setUrl(api);

  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
  }
};
  useEffect(<span class="hljs-function">() =&gt;</span> {
     getQsdb();
  }, [])

  <span class="hljs-keyword">const</span> getUrl = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> dashboardWrapper;
    <span class="hljs-keyword">const</span> containerDiv = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'dashboardContainer'</span>);
    <span class="hljs-keyword">const</span> params = {
      <span class="hljs-attr">url</span>: qsUrl?.url, 
      <span class="hljs-attr">container</span>: containerDiv,
      <span class="hljs-attr">parameters</span>: {
        <span class="hljs-attr">country</span>: <span class="hljs-string">'United States'</span>
      },
      <span class="hljs-attr">height</span>: <span class="hljs-string">'800px'</span>,
      <span class="hljs-attr">undoRedoDisabled</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">resetDisabled</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">footerPaddingEnabled</span>: <span class="hljs-literal">true</span>
    };
    <span class="hljs-comment">// eslint-disable-next-line no-unused-vars</span>
    dashboardWrapper = QuickSightEmbedding.embedDashboard(params);
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
      getUrl();
  }, [qsUrl.url]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"dashboardContainer"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EmbedDashboard;
</code></pre>
<p>• First, we imported Axios and the J<a target="_blank" href="https://github.com/awslabs/amazon-quicksight-embedding-sdk#step-3-create-the-quicksight-session-object">avaScript-embedding-SDK</a> into the app. It is also important to import “Auth” from aws-amplify if Amplify manages your authentication. If not, feel free to include your app user’s Jwtoken, email, and others.</p>
<p>• Next is to call our API using Axios. The request takes in the API URL, token, and the options parameter defined earlier.</p>
<p>• Then the getQsdb function gets called inside the useEffect and returns the embedded URL once the app loads.</p>
<p>• After that, we defined another function (getUrl( )) that embeds the URL into our app. Defining the dashboard URL and the container in which the dashboard will be embedded is the most important. Then, we used the quick sight-embedding-SDK that we defined earlier to call the embedDashboard() method and passed the params option.</p>
<p>• Finally, we called this getUrl function inside our useEffect and told it to run only when the URL is defined. And that’s it. Your dashboard should be up and ready.</p>
<h4 id="heading-bonus">Bonus</h4>
<p>If you need to embed multiple dashboards into your app. Then you will need an API URL that returns a list of the dashboards you need to embed with their respective IDs. The params option can also take in a dashboard Id like the one below so that you can be able to switch between multiple dashboards;</p>
<pre><code class="lang-JavaScript"><span class="hljs-keyword">const</span> params = {
      <span class="hljs-attr">url</span>: api.url,
      <span class="hljs-attr">dashboardId</span>: {
        <span class="hljs-attr">Id</span>: dashboard.id
      },
      …
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So far, we’ve been able to set up permissions on our web server, generate the embed URL from the backend and embed the URL into our React application. The <strong>embedDashboard()</strong> also supports other features such as On-screen filters, Download to CSV, Reset dashboard to defaults option, and many others. Feel free to explore them.</p>
]]></content:encoded></item><item><title><![CDATA[2022 Year-In-Review: Growth, Achievements, And Failures]]></title><description><![CDATA[To be honest, I’m not someone big on being optimistic about situations unless hope is needed. But this year was different. I knew my life and career needed a big leap, and for some reason, I hoped and believed it would happen. Maybe because I’m now m...]]></description><link>https://tech.racheltomi.com/2022-year-in-review-growth-achievements-and-failures</link><guid isPermaLink="true">https://tech.racheltomi.com/2022-year-in-review-growth-achievements-and-failures</guid><category><![CDATA[2022 year in review]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Tue, 27 Dec 2022 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1703953383686/d87db182-ca6b-4106-9665-7554adb6fad7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To be honest, I’m not someone big on being optimistic about situations unless hope is needed. But this year was different. I knew my life and career needed a big leap, and for some reason, I hoped and believed it would happen. Maybe because I’m now more confident in my skill after 2years of learning programming (now 3years), maybe.</p>
<h2 id="heading-a-very-quick-backstory"><strong>A Very Quick Backstory</strong></h2>
<p>I started programming in 2018 without a laptop. Did that for about 3months and couldn’t keep up, so I dropped it. Started again officially in 2019 while still at the university, this time with a laptop (thanks to my dad). Fast forward to 2021 ending, I got a 4-month contract job, and working with my boss instilled the confidence I needed. The contract job pay was below par, but I was okay with it for a start because I was still a student, and I wouldn’t trade the knowledge I gained from working with him for anything.</p>
<p>I was going to graduate that year and knew I needed to make more money to be able to support myself.</p>
<h2 id="heading-back-to-2022"><strong>Back To 2022</strong></h2>
<p>I make plans a lot and like to have almost everything in order or strategize well before taking a step.  2022 was different. I started the year very hopeful, with no exact plan in mind. I had worked my ass off the previous year and knew I only needed to improve my skill and get a good job. My resume was in good shape, my portfolio made sense, and I even had a <a target="_blank" href="https://blog.racheltomi.work/">tech blog</a>. Perfect. Now all I needed was to start applying for jobs.</p>
<p>I applied for jobs all through January, and nothing was forthcoming except rejection letters, of course. I used to work as a freelance copywriter and knew how sweet earning in dollars was. I already told myself I wanted to earn in dollars as a dev too, so I did not even bother to apply to Nigerian companies, except one, whose interview I failed woefully anyways due to lack of preparation. The rejection was a lot.</p>
<p>By February, I was getting impatient. But something good happened. I got a mail from a Nigerian company that wanted me to work with them. I did not apply to this company, so why? They said they came across my profile and wanted me to work for them. A good sign, finally. I went through with the interview and assessment. And you can already guess what happened. I accepted the offer letter because ‘half bread is better than none.’ I had to drop all my “I want to earn in dollars” shenanigans for the main time.<br />A few weeks after I accepted my offer letter, a friend told me about a possible job opening in a company in Europe. I did not take it seriously, for God knows why. I applied anyways. A week later, I was called for an interview, and it started to look real. I went through the 3 stages interview, and voilà, an offer letter came through. </p>
<p>All of this happened within the first few weeks of February. A lot can happen in 24 hours, really. It felt like a dream, and at the same time, it felt like a job well deserved after 2 years of hard work and persistence. I now had two jobs, just like that. I knew I wouldn’t be able to keep the two jobs. At least I did not want anything affecting my performance for the first few months. After a month, I had to resign from the Nigerian company. I felt bad, really, but it is what it is. The CEO was nice and even paid me for the few works I did for them.</p>
<p>I moved out of my parent’s house into mine after 2 months. And did I tell you I was going to be on probation for the first 3month and after that, my performance would be reviewed?  Honestly, I wasn’t even confident in my skill anymore. It felt like I was going to be sacked suddenly because I wasn’t good enough. New job trauma, lol.</p>
<p>3months later, this is one of the things my manager had to say.</p>
<p><img src="https://racheltomi.com/wp-content/uploads/2022/12/MOD-Nilton-Performance-Review-1024x111.jpg" alt="2022 year-in-review" /></p>
<h2 id="heading-personal-achievements-and-failures"><strong>Personal Achievements And Failures</strong></h2>
<p>I did not have time for many things I wanted to do this year because of my new job and environment. I was even burnt out a little at a point. But I pushed through regardless because…stars don’t give up : )</p>
<p>I launched my <a target="_blank" href="https://racheltomi.com/">blog</a> this year. I did this once but gave up because I had other priorities, but I’m back and better now. I share informative articles on personal development, career tips, tech, and productivity. This blog is very dear to me, and I’m working towards doing better next year, so make sure to stick around.</p>
<p>I indirectly started something I have always had in mind because I saw an opportunity to do so, and whew’ it failed. It’s an organization that’s focused on helping people, especially women, get into tech with the right platform (still coming up), resources, and mentorship. I got DMs from people who wanted to get into tech and needed help, and I decided to make something out of that since it was something I had always wanted to do. Maybe I wasn’t in the right headspace at the time, maybe. But if you’re willing to join a movement like this, please send me a direct message on <a target="_blank" href="https://twitter.com/theracheltomi">Twitter</a>. We can make something beautiful together.</p>
<p>It was a long year, and there is so much more I want to share. People and Lagos showed me shege, but I will just put a pin on it here.</p>
<p>I’m grateful to God for my journey so far. My journey from 2018 has not been a smooth one. I fought one one-on-one with Sapa so many times. But through it all, I’m a living testimony that with hard work, patience, and a good mindset, you will get what you want and much more.</p>
<p>2022 is what I envisioned it to be, and I hope 2023 is better.</p>
]]></content:encoded></item><item><title><![CDATA[How You Can Design Delightful API Architecture]]></title><description><![CDATA[Building, designing, and consuming APIs are some of the most important aspects of every developer’s career. An API should reflect the needs of users and, in this case, developers like you. As an app developer, you’ll need to do one of two things:

co...]]></description><link>https://tech.racheltomi.com/how-you-can-design-delightful-api-architecture</link><guid isPermaLink="true">https://tech.racheltomi.com/how-you-can-design-delightful-api-architecture</guid><category><![CDATA[api arc]]></category><category><![CDATA[api architecture]]></category><category><![CDATA[API Design]]></category><category><![CDATA[versioning]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Tue, 10 May 2022 09:39:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666172260860/p52zO0sPD.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Building, designing, and consuming APIs are some of the most important aspects of every developer’s career. An API should reflect the needs of users and, in this case, developers like you. As an app developer, you’ll need to do one of two things:</p>
<ul>
<li><p>communicate with external sources (i.e., third-party APIs) that provide the information you need</p>
</li>
<li><p>build an internal API for your company app or personal project</p>
</li>
</ul>
<p>However, it’s important to make your API easily accessible and flexible. So, how do you create an API that follows consistent API design, guidelines, and architecture?</p>
<p>In this post, I’ll share the best ways to design a good API architecture regardless of the API type or protocol used by your business or application. But before we do that, let’s recap the concept of an API.</p>
<h2 id="heading-what-is-an-api">What Is an API?</h2>
<p>API is an acronym for application programming interface. APIs are request types or methods that allow applications or programs to access back-end data and functionalities that enable developers to integrate and build complex applications. A good example of this is Facebook’s Graph API. Developers use this API regularly to get data into and out of the Facebook platform. This includes uploading photos, adding Facebook comments to websites, and so on. Another example is an operating system’s API like the Windows API, popularly known as Win32. The Windows API gives programs access to resources available to a Windows system like the file systems, the user registry, buttons, the scrollbar, and so on. This makes it easier for developers to implement necessary features without having to write programs from scratch every time. Now that you’ve had a refresher on what an API is, let’s talk about how they’re designed.</p>
<h2 id="heading-approaches-to-api-architecture-design">Approaches to API Architecture Design</h2>
<p>There are different approaches to designing an API architecture. REST, SOAP, and RPC are a few of the popular types.</p>
<h3 id="heading-soap">SOAP</h3>
<p>SOAP (simple object access protocol) is a messaging protocol for exchanging information between applications. It’s XML-based and can either exchange a document or call a remote procedure. In SOAP, we define a remote procedure in the sense of the client calling a specific method or procedure whenever a call is being made to the server.</p>
<h3 id="heading-rest">REST</h3>
<p>REST (representational state transfer) is a set of architectural styles that are used to design applications over HTTP. The idea behind REST is to use various URLs as access points to get resources from the server whenever developers need them. A RESTful API must adhere to the architecture created by Roy Fielding, whose REST guidelines include caching, client-server architecture, uniform interface, and so on.</p>
<h3 id="heading-rpc">RPC</h3>
<p>In RPC (remote procedural call), the client makes a remote procedural call by sending an HTTP request to the server and getting a response in return.</p>
<h2 id="heading-how-do-you-design-a-good-api">How Do You Design a Good API?</h2>
<p>When designing your API, you must follow some important patterns and best practices. These best practices will ensure that your API is user-friendly and functional, regardless of which design architecture you choose.</p>
<h3 id="heading-security">Security</h3>
<p>One of the most important factors to consider when designing your API is security. This is because building APIs that expose your data and application to the public also requires you to protect your system against attacks. And you don’t just have to protect your system, but also that of your partners, customers, and employees.</p>
<p>The more exposed an API is to the public, the more vulnerable it becomes to attacks. These attacks can include cross-site scripting, access control flaws, injections, credentials stuffing, and so on. From here, attackers can gain access to your network. This could lead to a data breach that can cause a company to lose its reputation, customers, and revenue. So, how do you secure your API?</p>
<p><strong>Employ a reliable API security service</strong>: Make use of services that help detect attacks and prevent them. For example, Traceable, an end-to-end security service for APIs and cloud-native applications, helps to automatically measure risks, discover and prevent attacks, defend your app, and analyze your data against threats.</p>
<p><strong>Follow best practices for API security</strong>: Ensure your API enforces a strong authentication and authorization solution such as Oauth2.0. It’s also important to limit the number of requests that your users can return to your application by implementing pagination. And lastly, remove sensitive information like access keys and passwords before you share your API with the public.</p>
<h3 id="heading-versioning">Versioning</h3>
<p>When designing your API, assume that you’ll always need to update or modify your API over time. You need to keep the developers that’ll use your API in mind when modifying your API. Developers need to know whenever you make a major update in your API to avoid their own app breaking. Including versioning in your app can be done in two ways:</p>
<ul>
<li><p>by including the API version in the header</p>
</li>
<li><p>by including the API version in the URL</p>
</li>
</ul>
<h3 id="heading-how-to-include-the-api-version-in-the-header">How to Include the API Version in the Header</h3>
<p>This approach involves requesting a specific API version using the Accept header, by providing more detail (such as the API version) about a given resource.</p>
<pre><code class="lang-plaintext">GET  /data/5 HTTP/1
Accept: application/vnd.mydata.v1+json
</code></pre>
<p>The Accept header here is used to provide the server with information about the type of response the client can accept. Here, the API URL doesn’t change across versions, but each version has a complex header attached to it. This method follows the HTTP standards, so it’s mostly recommended. How to Include the API Version in the URL</p>
<p>Including the API version in the URL gives users a quick understanding of the API version they are currently using. It also helps them avoid breaking their app by only calling the endpoint with the appropriate version. Here, anyone looking to call the endpoint can easily see in the URL that the API is in its fifth version:</p>
<pre><code class="lang-plaintext">http://www.companyname.com/api/data/v5
</code></pre>
<p>The downside to this is that with the release of so many versions, it becomes quite tasking for companies to keep providing support for these different versions, which might impact users. In my opinion, the best way companies can manage this situation is by;</p>
<ul>
<li><p>maintaining the older versions only for a certain number of years,</p>
</li>
<li><p>providing a release note or documents that explain the above decision to the users, and</p>
</li>
<li><p>maintaining only the last two or three versions with the current version.</p>
</li>
</ul>
<p>Although this method doesn’t adhere to the REST API principles, it’s the most common and easiest to manage.</p>
<h2 id="heading-performance">Performance</h2>
<p>Another requirement I consider one of the most critical when designing an API is performance. A slow API can be disastrous to the growth of a company. There are a few best practices you can keep in mind while designing your API to ensure that your API is fast and doesn’t break before or after production.</p>
<ul>
<li><p><strong>Caching</strong>: Caching is used to store data that is accessed frequently by the server. Instead of making a request to the server or database every time, one can use a cached version of this request, which helps to improve performance and increase load time.</p>
</li>
<li><p><strong>Define rate limits in your documentation</strong>: Defining a rate limit helps to limit the number of requests a specific client can make in a particular period. This helps to reduce the heavy load on the app and also improves performance. Here’s an example of what a rate limit looks like from GitHub documentation.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666171525028/jlaozz-7y.png" alt="github.png" /></p>
<p><a target="_blank" href="https://docs.github.com/en">GitHub documentation on rate limits</a></p>
<h2 id="heading-good-documentation">Good Documentation</h2>
<p>Speaking of documentation, no matter how good an API is, it’s going to be hard to use without proper documentation. A well-documented API doesn’t just attract more developers and decision-makers such as CTOs and product managers. It also makes it easier for them to test, use, or implement your API.</p>
<p>To write good documentation, you must ensure that it includes a section that provides a general overview of your API. With this, people can thoroughly understand everything your API does and how it can benefit them. From here, you can then provide a page for them to get started with the API.</p>
<p>You should also provide examples or a test environment where developers can test your API and make real calls. For example, take a look at this Spotify API documentation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666171642896/NlDw-iA2e.jpg" alt="spotify.jpg" /></p>
<p><a target="_blank" href="https://developer.spotify.com/documentation/web-api/quick-start/">Spotify Web API documentation</a></p>
<p>Spotify provides example code for developers. And it also makes a console available to enable developers to explore different endpoints. With this, developers can get familiar with the API endpoints. They can make requests, get responses, and learn the requirements needed to implement them.</p>
<p>Additionally, your API documentation must contain sections and features developers consider very important and expect to be present in every documentation. These include sections that walk developers through your authentication and authorization process, status codes and error messages, parameters, and so on. Last, make sure your API is readable. Avoid using technical jargon. Instead, write in plain language that’s easy for anybody reading your documentation to understand. A Well-Designed API Stands Out From the Crowd</p>
<p>Regardless of which architecture you choose, you need to create a well-designed API because developers are your customers. So, irrespective of whether your API is paid or free, providing them with excellent service is important. Excellent service includes making sure your API is easy to use, understand, and consistent. You also want to stay ahead of the competition, and a well-designed API gives you an edge. Consuming an API should be fun. But, unfortunately, tons of them are frustrating and difficult to use because of poor design. The key takeaway to designing a good API architecture is by adhering to the design principles mentioned above. These include good documentation, performance, security, and consistency.</p>
<p>Read the original post on <a target="_blank" href="https://www.traceable.ai/blog-post/delightful-api-architectures/">traceable</a></p>
]]></content:encoded></item><item><title><![CDATA[Differences Between Browser Router and Hash Router]]></title><description><![CDATA[Introduction to Routing in React
Routing is a very important aspect of every website. In React Js, routing is a process that allows a user to navigate to the different URLs that make up a React application. This is made possible through the use of a ...]]></description><link>https://tech.racheltomi.com/differences-between-browser-router-and-hash-router</link><guid isPermaLink="true">https://tech.racheltomi.com/differences-between-browser-router-and-hash-router</guid><category><![CDATA[hash-router]]></category><category><![CDATA[react router]]></category><category><![CDATA[Browser Router ]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Sun, 21 Nov 2021 09:02:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666169933374/dIXLEzyIz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction-to-routing-in-react">Introduction to Routing in React</h2>
<p>Routing is a very important aspect of every website. In React Js, routing is a process that allows a user to navigate to the different URLs that make up a React application. This is made possible through the use of a standard library system called React Router. With react-router, we can define multiple routes in our applications and render different components present in the app based on the route that matches the current URL being used. React router enables one to handle routing on the client side of a web application, thereby mitigating the issue of the old way of serving pages from the server side where pages refresh on every visit (i.e. making unnecessary calls to the server side).</p>
<p>To effectively understand this article, you need to have a basic understanding of react and react routing.</p>
<p>The react-router package consists of 3 different routers that we can make use of when building our apps. These routers include Browser Router, Hash Router, and Memory Router.</p>
<p>In this article, we will be focusing on the differences between Browser Router and Hash Router and why we should use them in our applications.</p>
<h3 id="heading-what-is-browser-router">What is Browser Router?</h3>
<p>Browser Router acts as a parent component that stores all of the other components present in our applications. It uses the HTML5 history API (pushState, replaceState, and the popstate event) by manipulating the browser session history to ensure that our UI matches its current URL.</p>
<p>A browser session history keeps track of all the pages visited in a browser tab and also provides useful properties that enable one to navigate back and forth in the browser using the user’s history.</p>
<p>Browser router makes use of the web server and also needs to be configured in other to function properly. This configuration is what makes routing on the client-side possible, otherwise one would get a “404 not found” error when visiting a particular page rendered in a browser.</p>
<p>Using the Browser router in our app, we will need to import it into our application like this.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { BrowserRouter <span class="hljs-keyword">as</span> Router } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
</code></pre>
<p>The above line means we just renamed “BrowserRouter” to “Router”, that’s all it does, And then, we can wrap the router around our application like this;</p>
<pre><code class="lang-javascript">ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)
);
</code></pre>
<p><strong>When to Use</strong></p>
<p>It’s best to use browser router when building large applications that require a server, though, the react-router-dom team advises one to use the browser router always and also try to configure it to work on all our applications.</p>
<h3 id="heading-what-is-hash-router">What is Hash Router?</h3>
<p>The Hash router on the other hand uses the client-side hash routing (i.e. window.location.hash) to ensure that your UI matches its current URL in your browser.</p>
<p>Whenever a new page gets rendered, the hash routes get appended to the browser URL, like this <code>localhost:3000/#/about</code>. The hash router usually does not require a web server to load a page because its hash URL ( e.g. localhost:3000/#/about ) cannot be read from the server, it’s usually handled by react-router, which makes configuration easier. Using hash router in your app is not recommended by the react-router-dom team because it does not support legacy browsers and might also be considered bad for SEO because search engines only rank contents that are available on the first load.</p>
<p>To use hash router in our app, we will also import the hash router;</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { HashRouter <span class="hljs-keyword">as</span> Router } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
</code></pre>
<p>and use it in our app like this;</p>
<pre><code class="lang-javascript">ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)
);
</code></pre>
<p><strong>When to Use</strong></p>
<p>If you’re trying to build static applications that only require you to use host providers like Netlify and SEO is not of utmost importance, then using hash router might be the best option.</p>
<h3 id="heading-major-differences-between-browser-router-and-hash-router">Major Differences Between Browser Router and Hash Router</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666169124774/9kpDh5F89.png" alt="Screenshot(1).png" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So far in this article, we have briefly described routing in ReactJs. We’ve explored the characteristics of both browser router and hash router, and have also understood their use cases. It is safe to say that both routers are good, but it is mostly advisable to use Browser router when building large applications that require one to have a hosting provider and also use Hash router when using host providers that only support static applications (e.g. Netlify).</p>
]]></content:encoded></item><item><title><![CDATA[Validating Props in React Components Using PropTypes]]></title><description><![CDATA[Proptypes is a package that is used to check how data types flow between react components. It’s a runtime type checking that helps to validate props passed between react components.
Why are PropTypes Essential??
When building applications in React, e...]]></description><link>https://tech.racheltomi.com/validating-props-in-react-components-using-proptypes</link><guid isPermaLink="true">https://tech.racheltomi.com/validating-props-in-react-components-using-proptypes</guid><category><![CDATA[prototypes]]></category><category><![CDATA[React]]></category><category><![CDATA[props]]></category><category><![CDATA[Props in reactjs]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Tue, 10 Aug 2021 15:29:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666105823433/SSYiK2aAp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Proptypes is a package that is used to check how data types flow between react components. It’s a runtime type checking that helps to validate props passed between react components.</p>
<h2 id="heading-why-are-proptypes-essential">Why are PropTypes Essential??</h2>
<p>When building applications in React, errors often occur when passing props to components. These errors can lead to challenging bugs, especially in extensive projects with numerous components.</p>
<p>This is mostly because JavaScript functions are flexible, allowing them to accept varying data types without generating errors. This makes it challenging for developers to pinpoint exactly where a problem originates when something goes wrong.</p>
<p>For example; The <em>Component.js</em> file below has two props called <em>name</em> and <em>bookTotal</em> with data types of string and number respectively.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

 <span class="hljs-keyword">const</span> Component = <span class="hljs-function">(<span class="hljs-params">{ name, bookTotal }</span>) =&gt;</span> {
   <span class="hljs-keyword">return</span> (
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
         my name is {name} and I have {10 + bookTotal} books
       <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Component;
</code></pre>
<p>Subsequently, we need to introduce our 'Component' into the 'App.js' file to pass props and visualize our app.</p>
<p>Now, imagine we accidentally pass the 'bookTotal' prop as a string instead of a number, as shown in the following code snippet. Our app would behave unexpectedly, yet no error would appear in the console.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;
 <span class="hljs-keyword">import</span> Component <span class="hljs-keyword">from</span> <span class="hljs-string">"./Component"</span>;

 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">return</span> (
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Tomisin"</span> <span class="hljs-attr">booksTotal</span>=<span class="hljs-string">"20"</span> /&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
   );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Below is what the result looks like;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666105976817/b9Mxz5Xlj.png" alt="prop1.png" /></p>
<p>In our <em>Component.js</em> file, we were trying to perform basic JavaScript addition by adding <em>10</em> and <em>bookTotal</em> prop together, which is meant to give us a total of <em>30 books</em>, but now our result shows <em>1020 books</em>, which is wrong.</p>
<p>JavaScript converted the number (10) into a string and proceeded to concatenate both strings without signalling an error that a number was anticipated instead of a string.</p>
<p>To avoid issues like the one above, it's crucial to diligently verify data types passed between components and confirm their alignment with expected types. To aid JavaScript in detecting such mistakes, PropTypes or TypeScript come in handy.</p>
<p>PropTypes and Typescript allow you to define and enforce the types of props being passed around your application. This helps to catch errors early on and makes it even easier to maintain and scale your codebase over time.</p>
<p>Using both methods is good, but in my opinion, your choice depends on how large your app is going to be or how you intend to use it. If you’re building a smaller app or a tool/library that will be used by others, using PropTypes might be the best option. And I’ll be talking more about PropTypes for this article.</p>
<h3 id="heading-getting-started">Getting Started</h3>
<p>To use PropTypes in react we need to install the dependency with the command below;</p>
<pre><code class="lang-javascript">npm install prop-types –save
</code></pre>
<p>Then you import it into your project files like this;</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">"prop-types"</span>;
</code></pre>
<h3 id="heading-using-proptypes-in-react">Using PropTypes in React</h3>
<p>Different validators in PropTypes can be used to check whether the data one received is valid.</p>
<h3 id="heading-basic-data-types">Basic data types</h3>
<p>This is the most basic way one can check if a prop is valid in react components. This is done by checking if the prop is one of the primitive data types in Javascript such as boolean, strings, numbers etc.</p>
<p>Here's a list of basic PropTypes for data type validation in JavaScript:</p>
<pre><code class="lang-javascript">PropTypes.bool; <span class="hljs-comment">//must be a Boolean</span>
PropTypes.object; <span class="hljs-comment">//must be an object</span>
PropTypes.number; <span class="hljs-comment">//must be a number</span>
PropTypes.string; <span class="hljs-comment">//must be a string</span>
PropTypes.func; <span class="hljs-comment">//must be a function</span>
PropTypes.array; <span class="hljs-comment">//must be an array</span>
PropTypes.symbol; <span class="hljs-comment">//must be a symbol</span>
PropTypes.any; <span class="hljs-comment">//Can be any property</span>
</code></pre>
<p>Referencing the previous example, to prevent passing a string instead of a number, enforce PropTypes in your component like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
 <span class="hljs-keyword">import</span> Component <span class="hljs-keyword">from</span> <span class="hljs-string">'./Component'</span>;
 <span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">'prop-types'</span>;

 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
 …

 Component.propTypes = {
   <span class="hljs-attr">name</span>: PropTypes.string,
  <span class="hljs-attr">bookTotal</span>: PropTypes.number
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Using this PropType, we can make sure that <em>“name”</em> is always a string and <em>“bookTotal”</em> is always a number, and when we do otherwise just like we did earlier we will have the warning below in our console;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666106161320/v94IE1usJ.png" alt="prop2.png" /></p>
<h3 id="heading-required-types">Required types</h3>
<p>To ensure that a particular prop is mandatory or required for a particular component, we can specify the isRequired property;</p>
<pre><code class="lang-javascript">…
 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
 …

 Component.propTypes = {
   <span class="hljs-attr">name</span>: PropTypes.string.isRequired,
   <span class="hljs-attr">bookTotal</span>: PropTypes.number.isRequired
 }

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Since we have specified that the two props are required, it is important to pass a value to both components. If we do not pass a value to <em>bookTotal</em> for example, we will receive the warning below in the console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666106312277/kooGTVCYQ.png" alt="prop3.png" /></p>
<h3 id="heading-multiple-types">Multiple Types</h3>
<p>Certain PropTypes only allow specific data types for props. They include:</p>
<ul>
<li><p>PropTypes.oneOfType</p>
</li>
<li><p>PropTypes.oneOf</p>
</li>
</ul>
<p>The <strong>'PropTypes.oneOfType'</strong> method permits specifying acceptable data types for a prop using an array of valid PropTypes.</p>
<p>Consider the example below:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">return</span> (
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Tomisin"</span> <span class="hljs-attr">bookTotal</span>=<span class="hljs-string">{4}</span> /&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
   );
 }

 Component.propTypes = {
  <span class="hljs-attr">bookTotal</span>: PropTypes.oneOfType([PropTypes.array, PropTypes.number]),
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In this case, 'bookTotal' can accept either a number or an array. Supplying a string, that doesn't match either type, triggers a warning.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666106394055/H1CmqSecj.png" alt="prop4.png" /></p>
<p>For 'PropTypes.oneOf', this approach involves an array of permissible values rather than an array of PropTypes. This is mostly useful if you have a set of named constants for different states. For example, you can set two constant states to the <em>bookState</em> prop, this means the said prop can only be valid when you have only the two states in the example below.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">return</span> (
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Tomisin"</span> <span class="hljs-attr">bookState</span>=<span class="hljs-string">"loadingbooks"</span> /&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
   );
 }

 Component.propTypes = {
  <span class="hljs-attr">bookState</span>: PropTypes.oneOf([<span class="hljs-string">"Readbook"</span>, <span class="hljs-string">"Unreadbook"</span>]),
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Since "<em>loadingbooks</em>" isn't part of the accepted array of props, an error occurs;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666106484856/L2dfxVvPr.png" alt="prop5.png" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have seen how PropTypes can be very useful in validating data types in React. Exploring the use of propTypes can be a good way to catch errors and also flag props as important when building our applications.</p>
<p>Thanks for reading :)</p>
]]></content:encoded></item><item><title><![CDATA[5 Essential CSS Selectors Every Developer Should Master]]></title><description><![CDATA[When I started writing CSS, my initial understanding revolved around using classes, IDs, types, and space selectors. I assumed that was the extent of it. However, over time, I learned more about new selectors, and in this article, I'm excited to shar...]]></description><link>https://tech.racheltomi.com/5-essential-css-selectors-every-developer-should-master</link><guid isPermaLink="true">https://tech.racheltomi.com/5-essential-css-selectors-every-developer-should-master</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[css selectors]]></category><category><![CDATA[Frontend Developer ]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Mon, 10 May 2021 14:48:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666104201296/FSbaUUwFt.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I started writing CSS, my initial understanding revolved around using classes, IDs, types, and space selectors. I assumed that was the extent of it. However, over time, I learned more about new selectors, and in this article, I'm excited to share some of them with you.</p>
<p>CSS selectors are the tools we use to pinpoint and style HTML elements. While there's an array of CSS selectors to choose from, I'll focus on discussing just five that are particularly powerful and useful.</p>
<ol>
<li><p>Direct Child Selector (&gt; sign).</p>
</li>
<li><p>General Sibling Selector (~ sign).</p>
</li>
<li><p>Adjacent Sibling Selector (+ sign)</p>
</li>
<li><p>Link Pseudo-classes</p>
</li>
<li><p>Negation Pseudo-class (:not( y ) )</p>
</li>
</ol>
<h3 id="heading-direct-child-selector-andgt-sign">Direct Child Selector (&gt; sign)</h3>
<p>This selector targets elements that are direct children of a container div. It's most effective when you only want to select the immediate children of a parent element. Consider this example;</p>
<pre><code class="lang-plaintext">&lt;div class="box"&gt;
  &lt;p&gt;This is the direct child&lt;/p&gt;
  &lt;div&gt;
    &lt;p&gt;this is children of child div&lt;/p&gt;
    &lt;p&gt;this is children of child div&lt;/p&gt;
  &lt;/div&gt;
  &lt;p&gt;This is the second direct child&lt;/p&gt;
&lt;/div&gt;

.box &gt; p {
  color: red;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103572005/wWrJQNCYj.png" alt="1selector.png" /></p>
<p><code>.box &gt; p</code> here targets only the <code>&lt;p&gt;</code> tags directly under the <code>.box</code> container div. The children of the child div don't turn red because they aren't direct descendants of the container div.</p>
<h3 id="heading-general-sibling-selector-sign">General Sibling Selector (~ sign)</h3>
<p>The ~ sign is a sibling combinator that targets all elements after the selected elements, it could be a div, type or just a class. Looking at the previous example; If you want to select all 'p' tags after the box-child div, we can do this;</p>
<pre><code class="lang-plaintext">&lt;div class="box"&gt;
  &lt;p&gt;This is the direct child&lt;/p&gt;
  &lt;div class="box-child"&gt;
    &lt;p&gt;this is children of child div&lt;/p&gt;
  &lt;/div&gt;
  &lt;p&gt;This is the first child&lt;/p&gt;
  &lt;p&gt;This is the second child&lt;/p&gt;
&lt;/div&gt;

.box-child ~ p {
  color: red;
}
</code></pre>
<p>And then, we get this result;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103687712/Z7clDBa1c.png" alt="2selector.png" /></p>
<p>Another example we can also look at is this; If you have a list of items and you want to select only some items on the list, we can also use this ~ selector.</p>
<pre><code class="lang-plaintext">&lt;div class="box"&gt;
  &lt;ul&gt;
    &lt;li&gt;Item 1&lt;/li&gt;
    &lt;li class="list1"&gt;Item 2&lt;/li&gt;
    &lt;li&gt;Item 3&lt;/li&gt;
    &lt;li&gt;Item 4&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

li.list1 ~ li {
  color: red;
}
</code></pre>
<p>So, here, you’re saying I want all Li’s after the Li with the class of .list1 to have a red colour. The third and fourth item here changes to a red colour without including the first and second item.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103776819/dIzwIc77l.png" alt="3selector.png" /></p>
<h3 id="heading-adjacent-sibling-selector-sign">Adjacent Sibling Selector (+ sign)</h3>
<p>Similar to the general sibling selector, this selector combines elements that have the same parent div. It only selects the element directly succeeding the former selector. In this example, to select only the list item directly after the Li with the list1 class, you can use the +(plus) symbol.</p>
<pre><code class="lang-plaintext">&lt;div class="box"&gt;
  &lt;ul&gt;
    &lt;li&gt;Item 1&lt;/li&gt;
    &lt;li class="list1"&gt;Item 2&lt;/li&gt;
    &lt;li&gt;Item 3&lt;/li&gt;
    &lt;li&gt;Item 4&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

li.list1 + li {
  color: red;
}
</code></pre>
<p>And you should get this as a result;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103877653/srYFh16dh.png" alt="iselector4.png" /></p>
<h3 id="heading-link-pseudo-classes">Link Pseudo-classes</h3>
<p>Using link pseudo-classes gives you the ability to style various states of your HTML link. These two pseudo-classes are worth noting:</p>
<ul>
<li><p><code>:link</code> targets unvisited links.</p>
</li>
<li><p><code>:visited</code> target links that have already been clicked.</p>
</li>
</ul>
<p>Here is an example;</p>
<pre><code class="lang-plaintext">&lt;div class="html-links"&gt;
  &lt;a href="#"&gt;This is the link I want to visit&lt;/a&gt;
&lt;/div&gt;

&lt;style&gt;
 a:link{
     color:blue;
 }
 a:visited{
     color: purple;
 }
    &lt;/style&gt;
</code></pre>
<p>You have this when the link hasn’t been clicked;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103995565/kFymP9HTf.png" alt="5selector.png" /></p>
<p>This is when the link has been clicked.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666104007601/uZYwqgUQY.png" alt="6selector.png" /></p>
<h3 id="heading-negation-pseudo-class-not-y">Negation Pseudo-class (:not( y ) )</h3>
<p>This selector is arguably the most powerful of all the selectors mentioned so far. The <code>:not()</code> pseudo-class enables you to select elements that don't match a specific selector.</p>
<p>For instance:</p>
<p>If you have a small div with a background image and a text overlay and you want to select the text displayed on this image and also style the div itself; Instead of using two different selectors to get this done(i.e. one to style the div and another one to negate it), you can use the <code>:not( )</code> selector, which will in this context select every element except those that do not match the argument passed. Just like the one below;</p>
<pre><code class="lang-plaintext">.div:not(img) {
  background-color: Red;
}
</code></pre>
<p>This code implies "select everything within <code>.div</code> that isn't an image." It's an efficient way to style elements that deviate from a particular rule.</p>
<p>Another example we can look at is the one below;</p>
<pre><code class="lang-plaintext">&lt;div class="blue"&gt;
   &lt;ul&gt;
     &lt;li&gt;Item 1&lt;/li&gt;
     &lt;li&gt;Item 2&lt;/li&gt;
     &lt;/ul&gt;
 &lt;/div&gt;
 &lt;div class="pink"&gt;
   &lt;ul&gt;
     &lt;li&gt;Item 3&lt;/li&gt;
    &lt;li&gt;Item 4&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;div class="black"&gt;
  &lt;ul&gt;
    &lt;li&gt;Item 5&lt;/li&gt;
    &lt;li&gt;Item 6&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

 &lt;style&gt;
 div:not(.pink){
    background-color: red;
}
 &lt;/style&gt;
</code></pre>
<p>Here we have two different divs with different classes and this code is saying, “Hey, I want to select all divs without the class of pink and I want them to all have a background of red. Which should give you this result;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666104172794/fb2dKpKYU.png" alt="7selector.png" /></p>
<h3 id="heading-wrapping-up">Wrapping up</h3>
<p>These CSS selectors are your tools for crafting finely tuned styles. Embrace their capabilities and improve your web development skills.</p>
<p>If you found this article helpful, don't hesitate to give it a like or share.</p>
<p>Thanks for reading.</p>
]]></content:encoded></item><item><title><![CDATA[Using Local Storage in JavaScript: A Comprehensive Guide]]></title><description><![CDATA[When I first delved into JavaScript, the term "local storage" was an unfamiliar one. It wasn't until I had to build a simple personal project that required data storage that I encountered this concept. I made a documentation of what I learnt and I’ve...]]></description><link>https://tech.racheltomi.com/using-local-storage-in-javascript-a-comprehensive-guide</link><guid isPermaLink="true">https://tech.racheltomi.com/using-local-storage-in-javascript-a-comprehensive-guide</guid><category><![CDATA[localstorage]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[cookies]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Sun, 20 Sep 2020 10:16:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666088085615/-2broWPft.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I first delved into JavaScript, the term "local storage" was an unfamiliar one. It wasn't until I had to build a simple personal project that required data storage that I encountered this concept. I made a documentation of what I learnt and I’ve decided to share them with you in this article.</p>
<p>There are various ways to store data within a user's web browser, and some of these methods include:</p>
<p><strong>Cookies</strong>: Using Cookies was pretty much the primary means of browser data storage, until recently. They have a maximum of 4kb of data storage, which means larger data can’t be stored all at once. Additionally, cookies were sent to the server with every request, accessible to both client and server sides. However, marking a cookie as HttpOnly prevented client-side scripts from accessing it.</p>
<p><strong>Web SQL</strong>: This method mimics relational databases and SQL, allowing data to be stored and retrieved using SQL commands. Unlike cookies, Web SQL can handle larger datasets effectively.</p>
<p><strong>Session Storage and Local Storage:</strong> Both of these methods involve storing data in JavaScript. The key distinction is that data in session storage gets wiped out upon page refresh or browser closure, while data in local storage persists even after refreshing the page.</p>
<p>For this article, I’ll be focusing more on “local storage”.</p>
<h3 id="heading-what-is-local-storage">What is Local Storage?</h3>
<p>Local storage is a technique to store information within a user's browser. It can store up to 5 MB of user data and can be accessed from any browser or window. Another thing to note is that local storage is domain-specific. In other words, you can only access the data you've saved when you're operating within the domain that houses that data.</p>
<p>For instance, if your website is "<a target="_blank" href="http://mytodos.com">mytodos.com</a>" and you've stored tasks like "read my book," "do my assignment," and "go to the market," you can only access these tasks when you visit "<a target="_blank" href="http://mytodos.com">mytodos.com</a>."</p>
<h3 id="heading-how-do-i-access-my-local-storage">How Do I Access My Local Storage?</h3>
<p>Local storage can be accessed right from your web browser since all stored data are saved across browsers in JavaScript. First, you need to go to your developer tools by pressing F12, then go to the application tab, right there, you will find your local storage <em>(F12 – application - storage – local storage – YourprojectPath ).</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666085288278/UdCgbwYC3.png" alt="ls1.png" /></p>
<p>Data is stored using named key/value pairs. When you store data, you assign it a key, and later, you retrieve that data using the same key.</p>
<p>To use local storage in Js, there are methods you need to get familiar with;</p>
<ul>
<li><p>setItem()</p>
</li>
<li><p>getItem( )</p>
</li>
<li><p>remove( )</p>
</li>
<li><p>clear( )</p>
</li>
</ul>
<p><strong>setItem( )</strong>: This method is used to save key/value pairs in local storage. The setItem method looks like the one we have below.</p>
<pre><code class="lang-plaintext">localStorage.setItem("name", "Tomi");
</code></pre>
<p>In this example, "name" serves as the key, and "Tomi" is the associated value. This key ("name") enables us to retrieve the corresponding value ("Tomi") later using the <code>getItem()</code> method.</p>
<p><strong>Fetching Stored Data with</strong> <code>getItem()</code></p>
<pre><code class="lang-plaintext">const user = localStorage.getItem("name");

//Tomi
</code></pre>
<p>getItem( ) is used to retrieve the value associated with the specified key ("name").</p>
<p>It's crucial to remember that local storage can only store strings. If objects or arrays are stored directly, they appear as "[object object]" in the console. To resolve this, use <code>JSON.stringify()</code> and <code>JSON.parse()</code> to convert them to strings and back into objects, respectively.</p>
<p>Looking at the example below, <code>getItem()</code> retrieves the value associated with the specified key ("name").</p>
<pre><code class="lang-plaintext">const user = {
  Name: "Tomi",
 Hobby: "coding",
};
localStorage.setItem("users", user);
console.log(localStorage.getItem("users", user));
</code></pre>
<p>Now, when we check this in our console, we get something like this [object object]</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666085626919/WQ--ijtk4.png" alt="ls2.png" /></p>
<p>This isn’t so useful because the real object information we need is not included. To fix this, this object has to be converted first to a string using the JSON.stringify( ) method and converted back to an object using the JSON.parse( ) method.</p>
<pre><code class="lang-plaintext">const user = {
  Name: "Tomi",
  Hobby: "coding",
};
localStorage.setItem("users", JSON.stringify(user));
console.log(JSON.parse(localStorage.getItem("users", user)));
</code></pre>
<p>Running this code, we get this in our console;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666085690406/yyTYfAyeQ.png" alt="ls3.png" /></p>
<p>JSON.stringify( ) here has successfully converted this object into a string and we’re able to parse it back into the local storage using JSON.parse( ).</p>
<p><strong>Removing Data with</strong> <code>removeItem()</code></p>
<p>The <code>removeItem()</code> method eliminates the value linked to a particular key:</p>
<p>Now, let’s try to remove the value we got earlier;</p>
<pre><code class="lang-plaintext">localStorage.removeItem("users");
</code></pre>
<p>If we try to get this value back using getItem(), we get <em>//Null</em> as the result.</p>
<pre><code class="lang-plaintext">const user = localStorage.getItem("users");

//Null
</code></pre>
<p><strong>Clearing All Data with</strong> <code>clear()</code></p>
<p>The <code>clear()</code> method wipes out all data stored in local storage using <code>localstorage.clear( )</code> method. This can be a little tricky. For safekeeping, consider copying and saving your code elsewhere before calling <code>localStorage.clear()</code>. Then, you can restore your code after refreshing the browser.</p>
<h3 id="heading-putting-it-all-together"><strong>Putting It All Together</strong></h3>
<p>To deepen your understanding, let's build a simple input page that stores user names in local storage even after a browser refresh. Let's start with the HTML and CSS components:</p>
<pre><code class="lang-plaintext">&lt;!DOCTYPE html&gt;
 &lt;html lang="en"&gt;
   &lt;head&gt;
     &lt;meta charset="UTF-8" /&gt;
     &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
     &lt;title&gt;Local storage&lt;/title&gt;
   &lt;/head&gt;
   &lt;body&gt;
     &lt;label for="name"&gt;Your Name:&lt;/label&gt;
    &lt;input id="nameTag" type="text" /&gt;
    &lt;a href="#" class="save-btn"&gt;Save&lt;/a&gt;

    &lt;div class="display"&gt;
      &lt;p&gt;&lt;/p&gt;
    &lt;/div&gt;

    &lt;script src="./script.js"&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>And our index.css looks like this, nothing serious, just some paddings and colours.</p>
<pre><code class="lang-plaintext">body {
   display: flex;
   align-items: center;
   justify-content: center;
   margin: 200px;
 }
 .save-btn,
 .click-btn {
   color: white;
  background-color: rgba(0, 0, 255, 0.726);
  font-weight: bold;
  padding: 10px 10px;
  text-decoration: none;
  border-radius: 5px;
  margin: 0 5px;
}
input[type="text"] {
  padding: 10px 10px;
  width: 30%;
}
.display {
  font-weight: bold;
  background-color: pink;
}
</code></pre>
<p>Moving on to JavaScript, initialize your variables:</p>
<pre><code class="lang-plaintext">const inputTag = document.getElementById("nameTag");
const saveButton = document.querySelector(".save-btn");
const Display = document.querySelector(".display");
</code></pre>
<p>Now that our variables have been defined, we can make the button clickable with an event listener:</p>
<pre><code class="lang-plaintext">saveButton.addEventListener("click", saveBtn);
</code></pre>
<p>Since our saveBtn doesn't exist yet, we have to define the function to save data:</p>
<pre><code class="lang-plaintext">function saveBtn(event) {
  event.preventDefault();
  const displayName = document.createElement("p");
  displayName.classList.add("showName");
  displayName.innerText = inputTag.value;
  Display.appendChild(displayName);
}
saveBtn();
</code></pre>
<p>What we’ve successfully done here is that we created another element within our HTML using createElement, added a new class and then called our HTML input value using <code>inputTag.value</code> and finally appended this value to the display div. Now that we can display our input value, the next step is to save this input value in our browser's local storage.</p>
<p>To achieve this, the first thing to do is call the DOMContentLoaded event.</p>
<pre><code class="lang-plaintext">document.addEventListener("DOMContentLoaded", showSavedResult);
</code></pre>
<p>This event runs when all the page’s DOM content has been loaded and parsed. Its target doesn’t include external resources like styles, images and so on, it sees the styles and images but doesn’t wait for them to completely load. So, this is the exact event that holds our local storage function, so it doesn’t get cleared even after the browser has been reloaded. Let’s move on to define our ‘showSavedResult’ function;</p>
<pre><code class="lang-plaintext">function showSavedResult() {
   let results;
   if (localStorage.getItem("results") === null) {
     results = [];
   } else {
     results = JSON.parse(localStorage.getItem("results"));
   }
   results.push(inputTag.value);
   localStorage.setItem("results", JSON.stringify(results));
}
</code></pre>
<p>What this code does is, it checks first if we already have an array stored in the local storage, if we don’t, it creates an empty array ( results = [ ]; ) and if we already have an array, we parse back our array and push our values into this empty array. We then set it back to a string using the setItem( ) and JSON.stringify( ) method. For this code to run successfully, we have to call our saveName function inside the main function.</p>
<pre><code class="lang-plaintext">function saveBtn(event){
    event.preventDefault();
   …
 showSavedResult();
}
</code></pre>
<p>By now, we should be seeing our arrays in the local storage, and we’ll also notice that our data doesn’t get cleared in the local storage if we try to refresh our browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666086487799/uJgyhpFCe.png" alt="ls4.png" /></p>
<p>Yes, we have successfully stored our small data in our local storage.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Local storage is not limited to what I’ve written above, but I hope it’s able to give you the basic understanding you need to make use of local storage. With the lesson, we should be able to set an item to the local storage, get back our item, remove our item and also get to clear all data present in the local storage. Feel free to leave a comment or share if this post was helpful to you.</p>
]]></content:encoded></item><item><title><![CDATA[How to spend more time not coding as a Freelance Developer]]></title><description><![CDATA[You were expecting some new tech, right? Not today !
via GIPHY
You’re always on a tight deadline, learning a new framework, or looking to deploy a new project ASAP. The list is endless and they all seem important. You wish you could spend more time w...]]></description><link>https://tech.racheltomi.com/how-to-spend-more-time-not-coding-as-a-freelance-developer-1</link><guid isPermaLink="true">https://tech.racheltomi.com/how-to-spend-more-time-not-coding-as-a-freelance-developer-1</guid><category><![CDATA[developers]]></category><category><![CDATA[burnout]]></category><category><![CDATA[stress of work]]></category><category><![CDATA[20-20-20 rule]]></category><category><![CDATA[work life balance]]></category><dc:creator><![CDATA[Rachel Tomi]]></dc:creator><pubDate>Mon, 31 Aug 2020 03:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666084316229/FVypvU6v3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You were expecting some new tech, right? Not today !</p>
<p><iframe src="https://giphy.com/embed/xTcf1mZ0qNYW9wjnMY" width="480" height="480" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/lifetimetv-dance-moms-xTcf1mZ0qNYW9wjnMY">via GIPHY</a></p><p></p>
<p>You’re always on a tight deadline, learning a new framework, or looking to deploy a new project ASAP. The list is endless and they all seem important. You wish you could spend more time with loved ones and have fun. I understand!</p>
<p>As developers, we usually don't pay attention to work-life balance, and the kudos given to spending more time in front of the screen is becoming unhealthy. 
I started out as a freelance copywriter and I’ll say I really struggled with time and stress management. I would spend most of the day in front of my PC and in the end feel like I haven't achieved anything for the day. Little did I know that a career transition would triple this effect. </p>
<p>As a web developer, working overtime is inevitable, but can be managed in a healthy way to reduce screen time. I definitely don't have it all figured out but with the little time I've spent as a developer, I've been able to pick up a few things I’ve learned along the way and I’ve decided to share some tips to help you manage stress, and also spend less time coding while getting more done.</p>
<h3 id="heading-freelance-developer-work-process">Freelance developer work process</h3>
<p>As a freelance developer, the daily routine mostly is to wake up, turn on your PC, code, code, eat, and code again, and these cycle repeats itself daily. It never stops. </p>
<p>To be a successful freelance developer, you want to be able to manage your clients, work on personal projects and still have enough time to relax and be taken care of. Here’re a few tips on how to get more done and still enjoy your free time:</p>
<p><strong> Be the boss of your own time</strong></p>
<p>I begin each day with a to-do list, which I prepare the night before or first thing in the morning. If you have kids, planning out your day can also mean planning what to do first between cleaning, attending to kids, and so on. It keeps you organized and focused.</p>
<p>So how do I do this? I organize my tasks in order of importance using an app called Todoist. A rule of thumb is that you should be real with yourself and not overthink your abilities. Try as much as possible to limit your tasks to what can be completed within 24 hours. Win the day slowly but surely.</p>
<p><strong> Work with Deadlines</strong></p>
<p>The human mind is tricky. It stretches to accommodate the time allocated to finish a task when it could have been completed in half the time. If you set 3 months to complete a 1-month project, it’s going to take 3 months for sure to complete. Why? You’ve convinced yourself that it’s impossible to get the project done faster. </p>
<p>Deadlines are super important! The code word is to START IMMEDIATELY. Even if it’s setting up a new project or creating an outline of what you’re going to do. You just have to START. Motivation comes from action. Once again, set a deadline and START. </p>
<p>Getting your jobs done on time means more free time. More free time, a better lifestyle.</p>
<p><strong>Pomodoro technique</strong></p>
<p>This technique helps you adhere strictly to timing and keeps you organized throughout the day.
For every project you work on throughout the day, you work for a certain period of time (25 min preferably) and take a short break afterward. This 25 min work time is called a "Pomodoro", which is an Italian word for "tomato". </p>
<p>How does it work?</p>
<p>The process is quite simple;
---- Pick a pen and write all the tasks needed to be completed for that day, or better still, use Todoist.
----Get a timer and set for 25min.
----Focus on a single task until the timer beeps.
----Tick what you've been able to achieve for this 25min and take a 5 min break.
----Increase your rest time to 20min-25min after 4 Pomodoro.
----Repeat this process until you get all your tasks done.</p>
<p>If 25min is too small for you to get a lot done, you can increase your work-time to an hour and make sure to take at least take 25min break each time your timer rings.
This technique is quite known among developers and has also been proven to be effective if taken seriously. </p>
<p><strong>Bonus Tips: Stay Healthy and Reduce Stress</strong></p>
<p><strong>Stay Hydrated</strong></p>
<p>Coding requires a lot of motivation and energy, and studies have also shown that dehydration increases fatigue and reduces motivation and energy levels. That's why taking lots of liquid while working is advisable. keeping your body system hydrated and drinking a lot of water will calm your nerves and help you reduce stress. </p>
<p>Another benefit of drinking a lot of water is it improves one’s memory and also helps reduce dryness which automatically causes tiredness, migraines and headaches.</p>
<p>If you’re not used to drinking water more often, there are few apps you can use to keep track of the amount of water that you drink and also get reminders to drink more water when you’ve not. Some of them are; Water drink reminder, water tracker, hydrillo and many others.</p>
<p><strong>Take a Walk</strong></p>
<p>Have you noticed that prolonged sitting for more than 8hours drops your energy level and you gradually start to lose concentration? That’s what happens when you sit for hours working without taking a break.</p>
<p>Sometimes, while coding and you’re stuck, instead of trying everything possible to fix that bug. Why not just relax!, take a deep breath, get up, and take a walk, somewhere quiet preferably. Stretching, playing, or taking a walk is an excellent way to boost productivity and also reduce mental fatigue.</p>
<p><strong>Practice the 20-20-20 Rule</strong></p>
<p>Over the years, screen time has always been an issue for programmers. I mean, we find ourselves gazing at our computer screens all day and it’s very likely you experience sore eyes, itchy eyes, blurred vision or even headaches, which are all as a result of eye strain. There’s a remedy for this. The 20-20-20 rule. </p>
<p>The 20-20-20 rule is basically looking 20feet away from your computer after every 20min for 20seconds. How do you even know if something is 20feet away? We are probably not going to measure the distance with a tape. What you can do is try to focus on something far away from you for 20sec, like a tree across the street or a house opposite your building. Practice this for every 20min and you’re good. </p>
<p>There are also free apps like Eye Care 20 20 20 that reminds you to take a break after every 20min in case you lost track of time.</p>
<p><strong>Find a Hobby</strong></p>
<p>Relaxing means something different for everyone. For some, it might be playing games or going to the parks and for others, it might be something entirely different. The point here is to "have fun". Do something that requires full focus (like playing video games). For me, it's movies. I make sure to watch at least a movie episode for an hour after completing a task. That way, I'm able to get my mind off anything that relates to code. You will be surprised at how much stress you're able to unload and how much bugs you're able to fix after taking some time off.</p>
<p><strong>Conclusion</strong></p>
<p>Work-life balance is a term developers don't really pay attention to, or maybe a number of us don't even know how to balance things up because we always find ourselves working on one task or the other. I hope reading this article will give you a clearer picture of how much free time you can have if your time is managed wisely. </p>
<p>Don’t hesitate to share if you find this useful. Till later. Byyeeeee.</p>
<p><iframe src="https://giphy.com/embed/5SCRRUSO5tSkKoR00P" width="480" height="445" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/fallontonight-tonight-show-mariah-carey-5SCRRUSO5tSkKoR00P"></a></p><p></p>
]]></content:encoded></item></channel></rss>