<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Makanju Oluwafemi</title>
    <description>The latest articles on DEV Community by Makanju Oluwafemi (@miracool).</description>
    <link>https://dev.to/miracool</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628059%2Fe5da7c2a-8dd4-4559-af13-0997e018ee5f.jpg</url>
      <title>DEV Community: Makanju Oluwafemi</title>
      <link>https://dev.to/miracool</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miracool"/>
    <language>en</language>
    <item>
      <title>Do people still genuinely care about technical articles ?</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Sun, 15 Feb 2026 23:42:17 +0000</pubDate>
      <link>https://dev.to/miracool/do-people-still-genuinely-care-about-technical-articles--1hfk</link>
      <guid>https://dev.to/miracool/do-people-still-genuinely-care-about-technical-articles--1hfk</guid>
      <description>&lt;p&gt;AI has spread like wildfire. In software development especially, it’s changing how we learn and solve problems. Instead of digging through documentation or reading long-form blog posts, many engineers now turn to AI for direct, tailored answers. It’s faster. It’s contextual. And if you know how to prompt well, it can even feel like having a senior engineer on demand.&lt;/p&gt;

&lt;p&gt;But it makes me wonder:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Do people still genuinely care about technical articles?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are long-form developer posts becoming obsolete, or are they evolving into something AI can’t replace?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is there a kind of depth, perspective, or storytelling that only comes from reading someone’s full thought process?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are we optimizing for speed over understanding?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AI gives answers, and articles often give context.&lt;/p&gt;

&lt;p&gt;Maybe the real question is :&lt;br&gt;
Are we building engineers who can ship fast or engineers who deeply understand what they’re shipping?&lt;/p&gt;

&lt;p&gt;Curious to hear your thoughts, hmmm.&lt;/p&gt;

</description>
      <category>community</category>
      <category>discuss</category>
      <category>software</category>
    </item>
    <item>
      <title>Web 3</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Fri, 13 Feb 2026 01:29:42 +0000</pubDate>
      <link>https://dev.to/miracool/web-3-5eek</link>
      <guid>https://dev.to/miracool/web-3-5eek</guid>
      <description></description>
    </item>
    <item>
      <title>Laid Off on the First Workday of the Year—and What Came Next</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Fri, 09 Jan 2026 08:52:55 +0000</pubDate>
      <link>https://dev.to/miracool/laid-off-on-the-first-workday-of-the-year-and-what-came-next-gii</link>
      <guid>https://dev.to/miracool/laid-off-on-the-first-workday-of-the-year-and-what-came-next-gii</guid>
      <description>&lt;p&gt;How would you feel if you were affected by a layoff on the very first workday of the year due to restructuring? You’d probably feel emotionally drained. And that’s okay; no one wants to lose their job, especially not on the first workday of a new year.&lt;/p&gt;

&lt;p&gt;This is usually the time when people reflect on the past year—though maybe it’s just me, and not everyone does this before work fully resumes in January, i.e., set goals and make plans for what’s ahead. You’ve already mapped things out, set targets, and envisioned how the year should go. Then, out of nowhere, boom! You’re out.&lt;/p&gt;

&lt;p&gt;Thinking about it now feels strange, because this is exactly where I find myself. But interestingly, the way I feel is quite different from everything I’ve just described.&lt;/p&gt;

&lt;p&gt;I have mixed feelings because, on one hand, I fancy the idea of a new challenge somewhere with a truly developer-focused product, and I have already been planning my next move and job search. On the other hand, I don’t like the idea of being laid off at all, especially since this is my first time experiencing something like this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Just to be clear, I was indeed offered more responsibility with an improved salary 2 months ago. However, we were unable to come to terms based on my expectations. In all, I'm grateful for the consideration.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How I’m Managing This Moment
&lt;/h2&gt;

&lt;p&gt;I do have plans for the year. That said, I’ll be prioritizing finding a new role above everything else right now for the sake of my mental health. This will probably be the first time in the past four years that I’m not actively working or employed by a company, so I’m still figuring out how to navigate this phase. It feels unfamiliar, but I’m confident I’ll find my footing.&lt;/p&gt;

&lt;p&gt;In the meantime, I plan to stay intentional and keep building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Working on personal projects in Rust and MOVE, driven by my growing interest in stablecoin adoption for global remittance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exploring and building projects in AI, really interested in AI agents, including MCP and related tooling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continuing to deepen my interest in web platforms and infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm a frontend engineer first before DevRel, so I have also been looking at still working, and that also helps improve my web platform experience due to the fact that I have managed deployment many a time.&lt;/p&gt;

&lt;p&gt;I know these are different areas, but my approach is to focus on them one at a time rather than all at once. Although I'm open to feedback and suggestions on how to manage this in the comment section. &lt;/p&gt;

&lt;h2&gt;
  
  
  What Next?
&lt;/h2&gt;

&lt;p&gt;This is probably the question on your mind, lol! A quick intro about me and what I have been up to over the years. My name is Femi, a developer relations engineer working at the intersection of product, engineering, and customer success. Over the past year, I transitioned from a frontend engineering background into full-time DevRel, where I’ve worked closely with tech leads, CTOs, heads of growth, and product managers to drive developer relations at an organizational level.&lt;/p&gt;

&lt;p&gt;Along the way, I’ve worn multiple hats as a frontend engineer, technical writer, and developer educator, helping shape developer experience through documentation, demos, and hands-on education. I’ve also hosted virtual developer events and delivered live demos at community and industry events, all focused on helping developers build confidently and successfully with the product.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkd7tlkg1xxtuofn78pfm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkd7tlkg1xxtuofn78pfm.jpg" alt="Nomba X wordpress lagos event" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Developer-focused event with the WordPress community in Lagos. I did a quick DEMO on how you can set up the Nomba payment plugin on the WooCommerce store&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’ve also hosted a virtual event on webhooks in payment integrations—you can find the recording on the &lt;a href="https://www.youtube.com/@nomba_developers" rel="noopener noreferrer"&gt;Nomba Developers&lt;/a&gt;&lt;br&gt;
YouTube channel.&lt;/p&gt;

&lt;p&gt;In addition, I’ve written technical articles for OpenReplay; you can &lt;a href="https://blog.openreplay.com/authors/makanju-oluwafemi-emmanuel/" rel="noopener noreferrer"&gt;view my profile and published work here&lt;/a&gt;&lt;br&gt;
. I’ve also contributed extensively to technical documentation for devtools and payment solution platforms, with my most recent work being end-to-end payment documentation for a &lt;a href="https://novacpayment.mintlify.app/docs/introduction/welcome-to-novac" rel="noopener noreferrer"&gt;Nigerian startup&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m currently looking for my next role and would love to join a developer-first or developer-plus company. If you have an open-source project you’d like me to contribute to as a technical writer, or know someone I should speak with, I’d really appreciate the connection.&lt;/p&gt;

&lt;p&gt;You can reach me directly at &lt;a href="mailto:makurseme@gmail.com"&gt;makurseme@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
      <category>devrel</category>
    </item>
    <item>
      <title>Learn how to authenticate with react JS</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Mon, 08 Sep 2025 23:20:27 +0000</pubDate>
      <link>https://dev.to/miracool/learn-how-to-authenticate-with-react-js-5c5n</link>
      <guid>https://dev.to/miracool/learn-how-to-authenticate-with-react-js-5c5n</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/miracool/how-to-manage-user-authentication-with-react-js-3ic5" class="crayons-story__hidden-navigation-link"&gt;How to manage user authentication With React JS&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/miracool" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628059%2Fe5da7c2a-8dd4-4559-af13-0997e018ee5f.jpg" alt="miracool profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/miracool" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Makanju Oluwafemi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Makanju Oluwafemi
                
              
              &lt;div id="story-author-preview-content-1708254" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/miracool" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628059%2Fe5da7c2a-8dd4-4559-af13-0997e018ee5f.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Makanju Oluwafemi&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/miracool/how-to-manage-user-authentication-with-react-js-3ic5" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 26 '23&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/miracool/how-to-manage-user-authentication-with-react-js-3ic5" id="article-link-1708254"&gt;
          How to manage user authentication With React JS
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/react"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;react&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/miracool/how-to-manage-user-authentication-with-react-js-3ic5" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;565&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/miracool/how-to-manage-user-authentication-with-react-js-3ic5#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              43&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to Setup Nomba Checkout on shopify</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Mon, 10 Mar 2025 11:49:06 +0000</pubDate>
      <link>https://dev.to/nomba-financial-service/how-to-setup-nomba-checkout-on-shopify-dfh</link>
      <guid>https://dev.to/nomba-financial-service/how-to-setup-nomba-checkout-on-shopify-dfh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Nomba provides a Shopify checkout plugin to accept payment in your online store. This plugin is similar to the &lt;a href="https://developer.nomba.com/plugins-and-sdk/overview" rel="noopener noreferrer"&gt;WordPress plugin&lt;/a&gt; simply because they are both used for accepting online payments. Also, it belongs to the no-code ecosystem. When building a Shopify store, there are different ways to accept payment. &lt;/p&gt;

&lt;p&gt;Typically, payment is a third-party thing for Shopify, but then they support some providers by default. This process is slightly different when you want to use Nomba as a payment provider in your Shopify store.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This Plugin is available to Nigerian merchants and it can be used to process internatio&lt;br&gt;
nal and local Payments.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;To use Nomba as your Shopify store payment provider, you will need to &lt;strong&gt;create an account&lt;/strong&gt; on the &lt;a href="https://nomba.com/" rel="noopener noreferrer"&gt;Nomba Website&lt;/a&gt;  &amp;gt;  go to the settings page on your dashboard. Click on Get &lt;strong&gt;API Keys&lt;/strong&gt;. The process is straightforward.&lt;/p&gt;

&lt;p&gt;These are the 3 things to get on the settings page before adding Nomba as a payment provider on your store. We provide the option to switch between live and test keys.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; ClientID&lt;/li&gt;
&lt;li&gt;Private Key&lt;/li&gt;
&lt;li&gt;Account ID&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step-by-step installation guide
&lt;/h2&gt;

&lt;p&gt;The step requires that you add Nomba as a third-party app. Look at &lt;a href="https://apps.shopify.com/nomba-gateway" rel="noopener noreferrer"&gt;Nomba Shopify plugin&lt;/a&gt; here and click on Install&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwm3aw065nbstyv1kalhy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwm3aw065nbstyv1kalhy.png" alt="app-download-page" width="800" height="378"&gt;&lt;/a&gt;&lt;br&gt;
When you click on Install, you will be redirected to your Shopify admin page, where you can now properly install the Nomba app.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6fes5iskfhfgojdwne0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6fes5iskfhfgojdwne0.png" alt="install" width="800" height="326"&gt;&lt;/a&gt;&lt;br&gt;
Click on Install to continue.&lt;br&gt;
When you successfully install this app, You will be redirected to Nomba payment gateway config page. On this page, You will add your Client ID, private secret, and account ID.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3850is016lm8wt6xayhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3850is016lm8wt6xayhj.png" alt="add-api-keys" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;You can get test and live keys on your settings page when you have completed setting up your dashboard.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;
&lt;br&gt;
&lt;/blockquote&gt;

&lt;p&gt;Click on the Ready checkbox, then click the Submit button, and you will get a notification that your data was saved without issue. Click go back to payment settings to activate the Nomba app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuaindakes9as0lp4rsgh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuaindakes9as0lp4rsgh.png" alt="setting-updated" width="800" height="202"&gt;&lt;/a&gt;&lt;br&gt;
This image shows a notification update, describing the status of the action you just completed.&lt;/p&gt;

&lt;p&gt;Click on the arrow left button and you will be redirected to a page where you can now activate Nomba for your Shopify app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2nj371dtygz4855mg3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2nj371dtygz4855mg3g.png" alt="setting-updated" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the activate button and you have successfully enabled Nomba as a payment service in your Shopify App. You can also choose to select  which card you would love your business to accept but for this tutorial we have all selected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpxqdoi48fipeoaah31x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpxqdoi48fipeoaah31x.png" alt="updated" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  conclusion
&lt;/h2&gt;

&lt;p&gt;With Nomba, you gain access to a reliable and secure payment solution that enhances your store’s checkout experience. Whether you're running a small business or scaling an enterprise, using Nomba as a payment provider, ensures that your customers enjoy smooth payment processing experience.  Now, your business can thrive without thinking of any payment hassle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://join.slack.com/t/nombadevelope-6l32082/shared_invite/zt-2yhdw0typ-LFC8ce2yBLlW9FAxJjplJQ" rel="noopener noreferrer"&gt;&lt;br&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdht4ofoyn%2Fimage%2Fupload%2Fv1736993672%2FArtboard_1_3x-50_efs2m3.jpg%2520align%3D" alt="affiliate-program" width="800" height="400"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>shopify</category>
      <category>nocode</category>
      <category>payment</category>
    </item>
    <item>
      <title>How Charge APIs Enhance Payment Processing in Fintech</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Wed, 29 Jan 2025 14:04:29 +0000</pubDate>
      <link>https://dev.to/nomba-financial-service/how-charge-apis-enhance-payment-processing-in-fintech-3o1n</link>
      <guid>https://dev.to/nomba-financial-service/how-charge-apis-enhance-payment-processing-in-fintech-3o1n</guid>
      <description>&lt;p&gt;As developers building payment solutions, we often encounter the term "charge," which can sometimes be confusing. In some cases, you might also come across the term Direct Charge. A charge refers to the specific action of processing a payment, which typically involves the authorization and capture of funds from the customer's payment method. Essentially, it’s the step where the transaction is finalized and the money is transferred from the customer to the merchant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importance of Charge API in modern payment systems
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Customization and Branding&lt;/strong&gt;&lt;br&gt;
Unlike traditional checkout systems, which typically redirect customers to a third-party page, the Charge API allows you to fully customize the payment experience. You can tailor the design and user flow to match your brand's identity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Security Features&lt;/strong&gt;&lt;br&gt;
Charge APIs often include built-in security measures like 3D Secure authentication and OTP verification to further protect against fraudulent transactions. This helps provide legitimate information about the card owner's identity. &lt;/p&gt;

&lt;p&gt;Charge API offers enhanced flexibility, better control, and a more personalized, secure payment experience than traditional checkout methods. This makes it an ideal choice for developers looking to take full control of their payment experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Nomba Charge API and the Process Flow
&lt;/h2&gt;

&lt;p&gt;The Nomba Charge API is a user-friendly payment solution that helps businesses securely process payments. Whether you’re accepting card payments, handling OTP-based authorizations, or offering transfer payments, Nomba Charge makes it simple. It lets you save customer card details for future purchases, authenticate transactions through OTPs, and track transaction statuses with ease. The process flow is straightforward, guiding you from getting order details to saving cards and even canceling incomplete transactions. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Process Diagram&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdht4ofoyn%2Fimage%2Fupload%2Fv1737944291%2Fresized-process-flow_dnvo1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdht4ofoyn%2Fimage%2Fupload%2Fv1737944291%2Fresized-process-flow_dnvo1c.png" alt="process-flow" width="800" height="893"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This flowchart provides developers with a comprehensive understanding of how the Nomba Charge API works. To begin, you'll create an order and submit the customer’s card details. An OTP will then be sent to the customer’s phone number. The customer can either enter the code to complete the verification or request a new code if the OTP expires. They also have the option to use a Flash account number. Once the process is complete, you can prompt the customer to decide if they’d like to save their card information for future payments. &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of Nomba Charge API
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Flash Payment Integration&lt;/strong&gt;&lt;br&gt;
The Charge API supports Flash payments, allowing users to complete transactions quickly and securely using their Flash account number. This feature simplifies payment by offering a convenient alternative to traditional card payments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Card Saving for Future Payments&lt;/strong&gt;&lt;br&gt;
With the Nomba Charge API, you can offer customers the option to save their card details securely for future transactions. This will make future payments faster and more convenient, improving the overall user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Secure OTP Verification&lt;/strong&gt;&lt;br&gt;
Security is important! The API uses OTP to verify user transactions. This two-factor authentication ensures that payments are processed securely and that only authorized users can complete a transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Charge API vs Traditional Payment Gateways
&lt;/h2&gt;

&lt;p&gt;Unlike traditional checkout systems, where customers are redirected to an external page to complete their payment and then returned to a callback URL set during transaction initialization, the Charge API allows you to create a fully customized payment gateway that aligns with your brand's look and feel.&lt;/p&gt;

&lt;p&gt;This gives you greater control over the entire payment process. With the Charge API, you can easily implement features such as saving customer cards for recurring payments, authorizing transactions via OTP (One-Time Password), and enabling 3D Secure authentication for enhanced security.&lt;/p&gt;

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

&lt;p&gt;Really glad you made it this far, haha! There are so many possibilities with building your product around the Nomba API. The charge API is just one of them. looking to explore our payment product? &lt;a href="https://developer.nomba.com/introduction/welcome-to-nomba" rel="noopener noreferrer"&gt;check here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://join.slack.com/t/nombadevelope-6l32082/shared_invite/zt-2yhdw0typ-LFC8ce2yBLlW9FAxJjplJQ" rel="noopener noreferrer"&gt;&lt;br&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqcsyuxzbdzb95cj4ml4.jpg" alt="affiliate-program" width="800" height="200"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>express</category>
      <category>fintech</category>
      <category>payment</category>
    </item>
    <item>
      <title>Learn how to accept payment in your woocomerce store. Wp Guys, check this out</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Tue, 28 Jan 2025 04:09:37 +0000</pubDate>
      <link>https://dev.to/miracool/learn-how-to-accept-payment-in-your-woocomerce-store-wp-guys-check-this-out-24ai</link>
      <guid>https://dev.to/miracool/learn-how-to-accept-payment-in-your-woocomerce-store-wp-guys-check-this-out-24ai</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/nomba-financial-service" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10242%2Faf65a922-ffc4-435b-832a-cdd78d08e892.png" alt="Nomba Financial Service" width="800" height="603"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628059%2Fe5da7c2a-8dd4-4559-af13-0997e018ee5f.jpg" alt="" width="800" height="999"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/nomba-financial-service/how-to-setup-nomba-checkout-on-woocommerce-4o05" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to setup Nomba checkout on Woocommerce&lt;/h2&gt;
      &lt;h3&gt;Makanju Oluwafemi for Nomba Financial Service ・ Jan 27&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#wordpress&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#woocommerce&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>How to setup Nomba checkout on Woocommerce</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Mon, 27 Jan 2025 01:01:45 +0000</pubDate>
      <link>https://dev.to/nomba-financial-service/how-to-setup-nomba-checkout-on-woocommerce-4o05</link>
      <guid>https://dev.to/nomba-financial-service/how-to-setup-nomba-checkout-on-woocommerce-4o05</guid>
      <description>&lt;p&gt;&lt;a href="https://woocommerce.com/" rel="noopener noreferrer"&gt;WooCommerce&lt;/a&gt; is a free online WordPress plugin that allows developers to manage online stores by providing quick setup configurations for product display, managing orders, and processing payments via the multiple payment gateways option provided.&lt;/p&gt;

&lt;p&gt;In this guide, we will walk through a step-by-step guide on how to add a &lt;a href="https://nomba.com/" rel="noopener noreferrer"&gt;nomba&lt;/a&gt; to your e-commerce website.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s important to know that this payment plugin is currently only available for Nigerian merchants.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;Before diving deep into the "how" of this guide, I have summarized what is expected. This will give you an overview or brief into what we need to do to get this checkout page up and running quickly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install WooCommerce, &lt;a href="https://wordpress.org/plugins/classic-editor/" rel="noopener noreferrer"&gt;Classic Editor Plugin&lt;/a&gt; and &lt;a href="https://wordpress.org/plugins/wc-nomba-gateway/#description" rel="noopener noreferrer"&gt;Nomba Payment Gateway for WooCommerce&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get Nomba API keys&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setup Nomba plugins&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Install a WordPress Plugin
&lt;/h2&gt;

&lt;p&gt;Adding a plugin in WordPress is synonymous with installing an NPM package when writing code. Ideally, plugins extend the capabilities of a project by enabling more functionalities. To add a plugin to your WordPress site, &lt;strong&gt;go to the WordPress admin&lt;/strong&gt; page. Select ** Plugins ** You should be presented with a page that looks Like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwsx28i3zn5sm6iiafys.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwsx28i3zn5sm6iiafys.jpg" alt="Add-plugin" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the &lt;strong&gt;Add Plugins button&lt;/strong&gt;, then search for the WooCommerce plugin. Click on install and activate.&lt;/p&gt;

&lt;p&gt;To install the Nomba Checkout Plugin, repeat the same process. When you search for the Nomba plugin, you will be presented with this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxccyvm7jw40z148cg8a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxccyvm7jw40z148cg8a.jpg" alt="Select-nomba-checkout" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This image shows the result of a search when a developer types in Nomba.&lt;/p&gt;

&lt;p&gt;It's possible that when you complete all of these installations and are about to test, you will be presented with an error description like the one in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frp8izq1vjbg8fqibdp84.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frp8izq1vjbg8fqibdp84.jpg" alt="fix-payment-error" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This image can be found on this &lt;a href="https://paygate.to/fix-woocommerce-there-are-no-payment-methods-available-error/" rel="noopener noreferrer"&gt;site&lt;/a&gt;, where you can learn more about why the error exists and how to fix it using the Classic Editor Plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get Nomba API keys
&lt;/h2&gt;

&lt;p&gt;When you have completed the installation of all the plugins, head over to &lt;strong&gt;Nomba&lt;/strong&gt; &amp;gt; &lt;strong&gt;Create account&lt;/strong&gt; &amp;gt; &lt;strong&gt;Dashboard&lt;/strong&gt;, click on settings on the right pane, and select &lt;strong&gt;Webhooks and API Keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkt6hmcge84rock4py23y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkt6hmcge84rock4py23y.png" alt="API-key-page" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A pictorial representation API keys page.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Setup Nomba Plugin
&lt;/h2&gt;

&lt;p&gt;Next, when you have completed the installation of all plugins, ensure that you activate the plugins so they can work as expected. Click on &lt;strong&gt;Manage&lt;/strong&gt; to add API keys.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupmbpcvj2lfusftrqbbv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupmbpcvj2lfusftrqbbv.jpg" alt="manage-plugin" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This Image explains how to manage the plugin  &lt;/p&gt;

&lt;p&gt;Next, you will add your Nomba credentials to the plugins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuxr7x2uy0n5k2symte4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuxr7x2uy0n5k2symte4.jpg" alt="API-key-page" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use the &lt;strong&gt;API keys and account ID&lt;/strong&gt; to connect with your Nomba account. Add the appropriate keys in the box. Select Test mode and Click &lt;strong&gt;Save Changes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Voila!, You have completed the installation and setup of your checkout plugin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accept payment on your Nomba Checkout Page
&lt;/h2&gt;

&lt;p&gt;If you are here, it means you have followed us through from beginning to end, and I'm glad you have been able to see how to install and use the Nomba WooCommerce plugin.&lt;/p&gt;

&lt;p&gt;Next, when you click on the checkout page, it will redirect you to the checkout page, and you can proceed to pay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lvcj40b73gmvwnqw34u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3lvcj40b73gmvwnqw34u.jpg" alt="checkout page" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;. This image shows a checkout order. &lt;/p&gt;

&lt;p&gt;When you click on Place Order, you will be redirected to this screen to complete your payment. &lt;br&gt;
Add your card details, and you are ready to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjyoy6qihzd27jrwvk2g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjyoy6qihzd27jrwvk2g.jpg" alt="checkout-card-page" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ve successfully integrated the Nomba payment gateway into your WooCommerce store. With this setup, you can now accept payments seamlessly on your checkout page. Just ensure your store is set up correctly with the provided API keys and the Nomba plugin.&lt;/p&gt;

&lt;p&gt;If you run into any issues, consult the Nomba developer community. You're now ready to offer your customers a smooth checkout experience!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdht4ofoyn%2Fimage%2Fupload%2Fv1736993672%2FArtboard_1_3x-50_efs2m3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdht4ofoyn%2Fimage%2Fupload%2Fv1736993672%2FArtboard_1_3x-50_efs2m3.jpg" alt="affiliate-program" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>wordpress</category>
      <category>woocommerce</category>
    </item>
    <item>
      <title>Submitting form data to Google Sheet from a React App</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Tue, 03 Sep 2024 16:03:27 +0000</pubDate>
      <link>https://dev.to/miracool/submitting-form-data-to-a-google-sheet-from-a-react-app-3o83</link>
      <guid>https://dev.to/miracool/submitting-form-data-to-a-google-sheet-from-a-react-app-3o83</guid>
      <description>&lt;p&gt;One thing that &lt;a href="https://www.google.com/" rel="noopener noreferrer"&gt;Google&lt;/a&gt; does that amazes me is the use cases that come with working with their workspace tools, be it Gmail, Google, or Meet. There are different ways to work with them. &lt;br&gt;
In this article, we will explore integrating Google Sheets, a workspace tool created to serve as an online spreadsheet. It's a feature-rich text editor where you can create, edit and collaborate. How do we intend to do this? Imagine we are making a waitlist for a start-up product and need to get people's data and store it for a campaign. You can leverage the Google Sheets API to get this data instead of worrying yourself about the problem of creating a backend and some database. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For you to follow this guide, honestly, I will say your experience in React or Vue won't matter, as basic Javascript knowledge can be applied to both. However, I will use a React app.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Introduction to AppScript
&lt;/h2&gt;

&lt;p&gt;Appscript is a JavaScript cloud-based platform that allows you to integrate with Google products, You can automate tasks across products like calendars, spreadsheets, and so on. Our focus in this article is Appscript for Google Sheets. &lt;/p&gt;
&lt;h2&gt;
  
  
  Create and set up a Spreadsheet
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://docs.google.com/spreadsheets/" rel="noopener noreferrer"&gt;spreadsheet on Google&lt;/a&gt; and create a new blank spreadsheet.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0jvb51viigheb4izca3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0jvb51viigheb4izca3.png" alt="Image description" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Extension&lt;/strong&gt; on the spreadsheet editor tab, you will be presented with a pop-up that looks like this.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3by28n0e0hc9gpc8enn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3by28n0e0hc9gpc8enn.png" alt="Image description" width="616" height="395"&gt;&lt;/a&gt; &lt;br&gt;
Click on Appscript, and you will be redirected to a new web-based editor to start writing your script. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4qe8kh0fkm0snfhz57x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4qe8kh0fkm0snfhz57x.png" alt="Image description" width="800" height="362"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Add a script and deploy your app.
&lt;/h2&gt;

&lt;p&gt;Next, copy and paste the code below into your editor.&lt;br&gt;
Next&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheetName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sheet1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptProp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PropertiesService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getScriptProperties&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initialSetup&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeSpreadsheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SpreadsheetApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getActiveSpreadsheet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;scriptProp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;activeSpreadsheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;doPost&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LockService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getScriptLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tryLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SpreadsheetApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptProp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSheetByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sheetName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastColumn&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;getValues&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLastRow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextRow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setValues&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;newRow&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextRow&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMimeType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ContentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTextOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMimeType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ContentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MimeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;releaseLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, click on the run button; you should get a success message in the output section.&lt;/p&gt;

&lt;p&gt;To deploy these changes, click on the deploy button; a small modal will appear underneath it. choose a new deployment.&lt;br&gt;
After that, a modal will pop up, Click select type settings and choose web app from the modal, then set "who has access" to anyone and "execute as" to me. Click on deploy; you should be redirected to the authorize screen. Follow the onscreen guide, and you should be okay.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvc09ipfaziqh62s8uoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvc09ipfaziqh62s8uoo.png" alt="Image description" width="800" height="542"&gt;&lt;/a&gt;&lt;br&gt;
A screenshot of how the modal should look.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you are authorizing, Google might not have verified your app, so click advance to the unsafe site when authorizing; no issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
When all steps have been completed, you should get a screen containing your deployment ID and Web App URL, Copy and save them somewhere because you will need them to be able to push from your React app to this sheet. Click done and you should be redirected to your web base editor.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjup644v44pymop2yjjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjup644v44pymop2yjjz.png" alt="Image description" width="532" height="695"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Set Up A trigger
&lt;/h2&gt;

&lt;p&gt;To set up a trigger, hover on the right pane; a swipe-out navigation layer will be presented, select &lt;code&gt;Triggers&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o7lxzizc9twgkbittuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o7lxzizc9twgkbittuy.png" alt="Image description" width="551" height="509"&gt;&lt;/a&gt;&lt;br&gt;
Click on the add trigger button. You will get a modal popup for adding your trigger function. These functions are divided into four; you can edit whichever one you want to use for this guide.&lt;/p&gt;

&lt;p&gt;Select &lt;code&gt;do Post&lt;/code&gt; for the function to run, &lt;code&gt;Head&lt;/code&gt; for deployment to run, &lt;code&gt;from spreadsheet&lt;/code&gt; for the selective event source, and &lt;code&gt;on form submit&lt;/code&gt; for the selective event type.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng24sfm2in4z99svvr5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng24sfm2in4z99svvr5z.png" alt="Image description" width="800" height="566"&gt;&lt;/a&gt;&lt;br&gt;
This is the image of how the triger modal should look.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a React Form and push data from your app
&lt;/h2&gt;

&lt;p&gt;To create a form, I have bootstrapped a react and typescript code. As I have said, you can always apply everything here in another framework; nothing too complicated. &lt;/p&gt;

&lt;p&gt;Next, copy this code into &lt;code&gt;App.tsx&lt;/code&gt;, it's just an example to show how to implement it in your own code. Please take note that you have to pass your app ID to the base URL; also, your payload data needs to be passed to &lt;code&gt;formData()&lt;/code&gt; for it to work.&lt;br&gt;
&lt;code&gt;App.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLFormElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Created At&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;APP_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;APP_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://script.google.com/macros/s/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;APP_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/exec`&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request was successful:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request Failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error during fetch:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handlePost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this code example, I created a form to get user emails and send them to the sheet when the user clicks on submit. When a user clicks, an event  &lt;code&gt;handlePost&lt;/code&gt; is triggered, passed through an asynchronous action, and it sends a request containing the input email address and the current time and date.&lt;/p&gt;

&lt;p&gt;If everything is successful, you should have your email and time in your Google sheet like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvd5w4rj95cp59i4wufma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvd5w4rj95cp59i4wufma.png" alt="Image description" width="504" height="556"&gt;&lt;/a&gt;&lt;br&gt;
A screenshot of the spreadsheet with inputted data from the form&lt;/p&gt;

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

&lt;p&gt;There are so many advantages to using Google Sheets, as it can be used in place of a backend to gather quick information from users from your app. There are other google workspace tool integration to explore, however, this will be our focus for now, hopefully later i can share articles on how to implement with other tools. Happy coding!    &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
      <category>vue</category>
    </item>
    <item>
      <title>MVVM in React: A beginner's guide</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Tue, 09 Jul 2024 08:28:41 +0000</pubDate>
      <link>https://dev.to/miracool/mvvm-in-react-a-beginners-guide-3cfi</link>
      <guid>https://dev.to/miracool/mvvm-in-react-a-beginners-guide-3cfi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;It is essential for all developers to give attention to code organization while creating modern software, since it may significantly improve developer experience, collaboration, code maintainability, and reuseability. There are different architecture that can be used to archive this. however, this article describe how to apply the Model-View-ViewModel (MVVM) architecture to improve the organization of your code.&lt;/p&gt;

&lt;p&gt;The Model-View-ViewModel (MVVM) software architecture model is widely used in the development of &lt;a href="https://www.techtarget.com/searchapparchitecture/definition/user-interface-UI" rel="noopener noreferrer"&gt;user interfaces&lt;/a&gt;. The user interface is divided into three components that are linked together: model, view,  and view-model. This architecture promotes &lt;a href="https://www.geeksforgeeks.org/separation-of-co" rel="noopener noreferrer"&gt;separation of concern&lt;/a&gt;. Without closely tying the user interface to the underlying business logic, it allows developers to work on multiple portions of the application at the same time. &lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding MVVM
&lt;/h2&gt;

&lt;p&gt;MVVM is a design pattern that promotes separation of concern in frontend development by separating the UI, application data, and business logic. This method makes sure that the presentation logic and application data can be managed independently, making the codebase more modular and maintainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components of MVVM
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model represents the application's data and business logic. It's made of the data structures and logics that contain how the application behaves. What I'm saying is that the model serves as the foundation upon which the entire application is built. It is also responsible for retrieving and manipulating data, as well as enforcing business logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The view is responsible for presenting the user interface to the end-user. The visual elements, such as buttons, text fields, and layouts, are kept in this part of the application; they are what users interact with. Unlike traditional architectures where the view is tightly coupled with the underlying logic, MVVM advocates for a more decoupled approach. The view should be passive and only concerned with rendering the view model's state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ViewModel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ViewModel acts as an intermediary between the view and the model. It serves as a bridge that translates the data and actions of the model into a format that the view component can understand. The View may stay portable and concentrate only on display issues because the ViewModel handles state management and presentation logic. They are connected by a channel, allowing them to exchange messages when necessary. This strategy promotes improved concern separation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing MVVM in React
&lt;/h2&gt;

&lt;p&gt;In this example, we will create a walk-through guide on how to implement a simple feature where users can add and list tasks. &lt;/p&gt;

&lt;p&gt;To get started, you should have a fresh installation of &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;react&lt;/a&gt; ready. or better still copy and paste this code on your terminal to create a project.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-app mvvm-app
&lt;span class="nb"&gt;cd &lt;/span&gt;mvvm-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After setting up, the first thing to do is create a model for managing data and business logic.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;TaskModel.js&lt;/code&gt;, copy and paste this code into it.&lt;br&gt;
&lt;code&gt;TaskModel.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

  &lt;span class="nf"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This code has a &lt;code&gt;TaskModal&lt;/code&gt; class, which consist of a constructor that is used for saving all the task in an array. It also consist of two methods, &lt;code&gt;addTask&lt;/code&gt; and &lt;code&gt;getAllTasks&lt;/code&gt; both of which are for adding and getting tasks.&lt;/p&gt;

&lt;p&gt;Next, you will create the render view using &lt;code&gt;App.js&lt;/code&gt; and show  &lt;br&gt;
&lt;code&gt;App.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useTaskViewModel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./view-model/TaskViewModel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;taskInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTaskInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getAllTasks&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTaskViewModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAddTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTaskInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getAllTasks&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="nx"&gt;Manager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main text-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add a task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;taskInput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTaskInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAddTask&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main task-wrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Tasks&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;hr&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;task-item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="p"&gt;))}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;list-not-found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;There&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This component serves as the main interface for the tasks. It utilizes local state to manage the input for adding tasks &lt;code&gt;taskInput&lt;/code&gt;  and the list of tasks &lt;code&gt;tasks&lt;/code&gt;. The &lt;code&gt;useTaskViewModel&lt;/code&gt; hook is used to interact with the &lt;code&gt;ViewModel&lt;/code&gt;, enabling functionality for adding tasks &lt;code&gt;addTask&lt;/code&gt; and retrieving all tasks &lt;code&gt;getAllTasks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;handleAddTask&lt;/code&gt; function add task to the list, triggering the &lt;code&gt;addTask&lt;/code&gt; method with the current input value, resetting the input field, and updating the task list with the newly added task. The JSX markup structures the UI with input and button elements for adding tasks and a list to display existing tasks. Conditional rendering ensures that a message is displayed when there are no tasks present.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.main-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#20205d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.main-container&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.main-container&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.text-input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.text-input&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.78px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.text-input&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.task-wrapper&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this CSS code example, we style the task management application's user interface. We center the content, define the main container's appearance, and set styles for text, input fields, buttons, and task items.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv905rvle9bj061wz2nzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv905rvle9bj061wz2nzv.png" alt="output-1" width="503" height="291"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
This image shows the output of the image. task has not been added in this image but the &lt;a href="https://www.investopedia.com/terms/h/html.asp" rel="noopener noreferrer"&gt;HTML(HyperText Markup Language)&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS" rel="noopener noreferrer"&gt;CSS(Cascading Style Sheets)&lt;/a&gt; has been implemented.&lt;br&gt;
&lt;code&gt;TaskViewModel.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;TaskModel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../model/TaskModel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useTaskViewModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;taskModel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TaskModel&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;taskModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getAllTasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;taskModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getAllTasks&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;useTaskViewModel&lt;/code&gt; hook contains all the logic, data, and functionality related to tasks. It uses the &lt;code&gt;useState&lt;/code&gt; hook to initialize a TaskModel instance, which handles task-related operations. &lt;code&gt;addTask&lt;/code&gt; Accepts a task as input and delegates the task addition functionality to the TaskModel instance, which adds the task to the internal data structure.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getAllTasks&lt;/code&gt; Retrieves all tasks stored in the &lt;code&gt;TaskModel&lt;/code&gt; instance and returns them as an array. Components can easily interact with tasks using these methods without directly accessing the underlying data or business logic of the task model.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F57lrnyn2qqqgn3y600c9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F57lrnyn2qqqgn3y600c9.png" alt="output-2" width="488" height="375"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
This image shows the output of the task user interface, when a user add task to it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Using MVVM in React
&lt;/h2&gt;

&lt;p&gt;React applications can achieve even greater levels of modularity, maintainability, and testability. In this section, we'll explore how MVVM enhances the developer experience by focusing on three key benefits: separation of concerns, reusability and maintainability, and enhanced testability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separation of concerns
&lt;/h3&gt;

&lt;p&gt;MVVM promotes separation of concern by giving each of its components distinct roles. The model represents the data, business logic of the application, and state management. The visual elements that are visible to users are represented by the view, which is composed of JSX components that make up the user interface. Presentation logic is incorporated into the view model. It manages data transformation, ensuring that the data in the model and the view's display communicate with one another without interruption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reusability and maintainability
&lt;/h3&gt;

&lt;p&gt;By isolating presentation logic in the ViewModel, developers can reuse this logic across multiple components without duplicating code. This promotes code reuse and simplifies maintenance efforts. Also, with clear separation between Model, View, and ViewModel, React applications built using MVVM are inherently more modular. It is easier to understand, change, and expand the functionality of the application when each component is able to concentrate on its own functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhanced testability
&lt;/h3&gt;

&lt;p&gt;Developers can write unit tests for the ViewModel, which contains the application's business logic. These tests verify that the ViewModel behaves correctly under various conditions without needing to render the UI components. They can also write integration tests to ensure that the model, view, and view work together as expected. These tests validate the end-to-end functionality of the application, covering interactions between different layers. In essence, MVVM makes it easier to write good tests for React components. This results in software that is more stable, dependable, and bug-free.&lt;/p&gt;

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

&lt;p&gt;Dependable systems that enhance testability, ensure code separation, and eliminate all code duplication are necessary while developing scalable applications. All these are what MVVM stands for. Look it over now, implement it in your project, and improve as a developer. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to Create a Custom Hook for Seamless Data Retrieval with React.</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Tue, 30 Apr 2024 13:32:17 +0000</pubDate>
      <link>https://dev.to/miracool/react-magic-how-to-create-a-custom-hook-for-seamless-data-retrieval-4hj4</link>
      <guid>https://dev.to/miracool/react-magic-how-to-create-a-custom-hook-for-seamless-data-retrieval-4hj4</guid>
      <description>&lt;h2&gt;
  
  
  introduction
&lt;/h2&gt;

&lt;p&gt;Custom hooks in &lt;a href="//react.dev"&gt;react&lt;/a&gt; allow developers to extract logic that is needed in multiple components into a standalone function. This can apply to making API requests, state management, or even side effects.&lt;/p&gt;

&lt;p&gt;Side effects in React refer to any operation that occurs outside the scope of the component's render function, such as data fetching, subscriptions, or DOM manipulation.&lt;/p&gt;

&lt;p&gt;There are a few rules that govern hooks creation in React; you can check them [here]: &lt;a href="https://legacy.reactjs.org/docs/hooks-rules" rel="noopener noreferrer"&gt;https://legacy.reactjs.org/docs/hooks-rules&lt;/a&gt;. However, make sure your hook name starts with &lt;code&gt;use&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Service That Handles API Requests
&lt;/h2&gt;

&lt;p&gt;When working on features that require logic duplication, for example, you need to send a &lt;a href="https://www.w3schools.com/tags/ref_httpmethods.asp" rel="noopener noreferrer"&gt;GET&lt;/a&gt; request to &lt;code&gt;/api/allproduct&lt;/code&gt;, &lt;code&gt;/api/singleproduct/:id&lt;/code&gt; and so on. You can decide to create a service that handles all these requests in a single file and export them to use in another file.&lt;/p&gt;

&lt;p&gt;To understand what I'm saying in essence, walk with me!&lt;br&gt;
Do ensure that you have a React project set up already, or copy this code to do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-app hooks-example
&lt;span class="nb"&gt;cd &lt;/span&gt;hooks-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, copy this code to add &lt;a href="https://www.npmjs.com/package/axios" rel="noopener noreferrer"&gt;axios&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that you are all set, create a folder and name it &lt;code&gt;service&lt;/code&gt; in your &lt;code&gt;src&lt;/code&gt; directory. Inside this folder, create an &lt;br&gt;
&lt;code&gt;evenService.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eventService.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api-url/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchAllProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api/all-products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Return only the products data&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to fetch all products: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Include more descriptive error message&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch all products. Please try again.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example code, I have defined an Axios instance &lt;code&gt;apiService&lt;/code&gt; with a &lt;code&gt;baseURL&lt;/code&gt; and default &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" rel="noopener noreferrer"&gt;headers&lt;/a&gt; for making HTTP requests to an API. It also defines a function &lt;code&gt;fetchAllProduct&lt;/code&gt; for fetching all products from the API using a GET request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is this approach better?
&lt;/h3&gt;

&lt;p&gt;I won't say it's not better, but then things can be implemented better by putting this logic into a custom hook called &lt;code&gt;useApi&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is my take&lt;/strong&gt;&lt;br&gt;
If I continue like this, the &lt;code&gt;eventService.js&lt;/code&gt; file will soon become so long and unorganized. I will have to add a new export function for each API request. Rewriting the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" rel="noopener noreferrer"&gt;async&lt;/a&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await" rel="noopener noreferrer"&gt;awaits&lt;/a&gt; for everyone of the function. &lt;br&gt;
This does not seem to be perfect; remember the DRY (Do Not Repeat Yourself) rule.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a Custom Hook for API requests
&lt;/h2&gt;

&lt;p&gt;You can edit the &lt;code&gt;eventService.js&lt;/code&gt; file by removing the &lt;code&gt;fetchAllProduct&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;Then add export to &lt;code&gt;apiService&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api-url/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a folder and name it &lt;code&gt;hooks&lt;/code&gt; in your &lt;code&gt;src&lt;/code&gt; directory. Then, create a &lt;code&gt;useApi.js&lt;/code&gt; file. Import your &lt;code&gt;apiService&lt;/code&gt; and use it here.&lt;/p&gt;

&lt;p&gt;Copy and paste this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleEndpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unsupported HTTP method: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;};&lt;/span&gt;

     &lt;span class="nf"&gt;handleEndpoint&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this example, we created a custom hook called &lt;code&gt;useApi&lt;/code&gt;. It encapsulates API fetching logic in a reusable manner.  &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; hooks are used to manage loading state, fetched data, and potential errors. When invoked with a specified API endpoint, HTTP method, and optional request body (req), it triggers an asynchronous operation to fetch data from the API using the provided method (GET, POST, PUT, DELETE). Upon completion, it updates the component's state accordingly, setting loading to false, storing the retrieved data in data, and capturing any errors in error. &lt;/p&gt;

&lt;p&gt;This hook allows reusability, reduces the complexities of API interaction, and promotes cleaner code.&lt;/p&gt;

&lt;p&gt;With these few points of mine, I hope I have been able to convince and not confuse you that creating a custom hook for your API request will significantly advance modularity and reusability. Happy Coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The Human Element in Testing: Nurturing Soft Skills for Testers</title>
      <dc:creator>Makanju Oluwafemi</dc:creator>
      <pubDate>Wed, 17 Jan 2024 22:56:20 +0000</pubDate>
      <link>https://dev.to/miracool/the-human-element-in-testing-nurturing-soft-skills-for-testers-173m</link>
      <guid>https://dev.to/miracool/the-human-element-in-testing-nurturing-soft-skills-for-testers-173m</guid>
      <description>&lt;p&gt;Within the dynamic field of software testing, the need for soft skills in addition to technical competency is being recognized more and more. To transform testers from simple executors into strategic contributors, this article examines the importance of communication, teamwork, adaptability, and empathy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collaboration:
&lt;/h2&gt;

&lt;p&gt;Highlighting how important good teamwork is to the outcome of testing projects and examining the collaborative aspect of modern software development as a tester, the focus is on testers participating actively in conversations, brainstorming sessions, and offering insightful criticism. &lt;/p&gt;

&lt;p&gt;The main takeaway is that the tester's responsibilities go beyond specific tasks to include meaningful engagement in a team environment, where their observations and suggestions greatly enhance the process's overall effectiveness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptability:
&lt;/h2&gt;

&lt;p&gt;A flexible approach has been highlighted by using the term "agile" to characterize the testing process. The emphasis is on testers' capacity to adjust to changes without difficulty, understanding that in the dynamic world of software testing, flexibility is not only helpful but necessary.&lt;/p&gt;

&lt;p&gt;The term "flexible approach" denotes the ability to respond and adjust swiftly to changing circumstances, acknowledging the unpredictable nature of software development and testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Empathy:
&lt;/h2&gt;

&lt;p&gt;The importance of empathy in the testing process is emphasized in this section, which shows how it can change the process from being mechanical to being human-centered. It acknowledges that comprehension of end users' viewpoints and demands is essential to efficient testing by highlighting the necessity for testers to have empathy for end users.&lt;/p&gt;

&lt;p&gt;The phrase "empathy-driven testing" describes an approach in which testers immerse themselves in the user experience and move beyond technical assessments. Testers are better equipped to replicate real-world events thanks to this sympathetic understanding. Testers take into account how people interact with the software in their particular situations rather than focusing only on technical features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft Skills Training:
&lt;/h2&gt;

&lt;p&gt;There are a series of programs that are recommended, including workshops that concentrate on communication skills, team-building activities, and scenarios that require flexibility. The main objective is to produce well-rounded testing teams that possess the interpersonal and adaptable abilities needed to flourish in the fast-paced, team-oriented settings typical of modern software development projects.&lt;br&gt;
It will help testers gain valuable training meant to improve their capacity to collaborate, communicate, and adjust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Balancing Technical and Soft Skills:
&lt;/h2&gt;

&lt;p&gt;Testers become more than just implementers thanks to this connection; they become important members of a team. This highlights how important testers are in helping technical and non-technical stakeholders communicate with each other. Assisting in the efficient translation of complex technical jargon into insightful knowledge, testers establish themselves as important participants in the larger project environment and improve comprehension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategic Imperative:
&lt;/h2&gt;

&lt;p&gt;The word "strategic" suggests that testing procedures involve intentional and essential elements. The cornerstone for testing success is positioned as the human aspect, which is defined by efficient communication, smooth collaboration, adaptability, and empathy. This emphasizes how crucial soft skills are for negotiating the complex testing environment's problems and highlights their strategic significance for testers aiming for excellence in their line of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts:
&lt;/h2&gt;

&lt;p&gt;The final section focuses on the testers' transformation from simple executors to strategic partners. The word "evolution" emphasizes a wider range of skills and denotes a development beyond conventional roles. The emphasis on complete growth means that, in addition to developing testers' technical expertise, it also acknowledges that they are human beings who add a human touch to the accuracy of software testing. This understanding of the human aspect becomes essential for navigating the testing industry's constantly shifting terrain, implying that its future relevance rests in the combination of expertise and the recognition of testers as essential participants in the complicated and dynamic field of software development.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
