<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Calebbenjamin Blog]]></title><description><![CDATA[I'm a frontend developer and an optimist, passionate about optimization, business goals, and, most importantly Startups and Founders.]]></description><link>https://blog.calebbenjamin.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 11:13:25 GMT</lastBuildDate><atom:link href="https://blog.calebbenjamin.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Approach Frontend Performance in 2025 (and Why It Still Matters)]]></title><description><![CDATA[This guide is for frontend developers, senior engineers, tech leads, and performance-focused product teams who want to build faster, more scalable, and user-first web applications in 2025. Whether you're working with React, Next.js, Vue, or Svelte, t...]]></description><link>https://blog.calebbenjamin.com/how-to-approach-frontend-performance-in-2025-and-why-it-still-matters</link><guid isPermaLink="true">https://blog.calebbenjamin.com/how-to-approach-frontend-performance-in-2025-and-why-it-still-matters</guid><category><![CDATA[#WebPerformance #FrontendEngineering #ReactJS #NextJS #CleanCode #UserExperience #SoftwareArchitecture #DeveloperExperience #TypeScript #SeniorEngineer]]></category><category><![CDATA[web performance]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[developer experience]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[react js]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[clean code]]></category><category><![CDATA[user experience]]></category><dc:creator><![CDATA[Caleb Benjamin]]></dc:creator><pubDate>Fri, 18 Apr 2025 23:08:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745017249965/9421720d-c62a-4d40-8abe-d9bc770cc93c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This guide is for <strong>frontend developers, senior engineers, tech leads, and performance-focused product teams</strong> who want to build faster, more scalable, and user-first web applications in 2025. Whether you're working with <strong>React, Next.js, Vue, or Svelte</strong>, the principles in this post will help you make smarter decisions about speed, architecture, and experience.</p>
<p>If you care about shipping apps that don’t just <em>work</em>, but <em>wow</em>—this is for you.</p>
<p>Web performance in 2025 is no longer just about page speed. It's about delivering experiences that feel fast, reliable, and responsive—across devices, network conditions, and user expectations.</p>
<p>We're building more dynamic and complex interfaces than ever before, and users aren’t just comparing your app to competitors—they’re comparing it to <strong>TikTok, YouTube, and ChatGPT</strong>.</p>
<p>That means performance isn’t just a technical metric. It’s a <strong>product decision.</strong></p>
<p>In this article, I’ll walk you through how I approach performance as a senior frontend engineer today—from architecture to tooling to culture.</p>
<h2 id="heading-1-start-with-user-experience-not-lighthouse"><strong>1. Start With User Experience, Not Lighthouse</strong></h2>
<p>Before I open any performance profiler or run Lighthouse, I ask:</p>
<ul>
<li><p><strong>How fast does the app <em>feel</em> to a real user?</strong></p>
</li>
<li><p>Does the page show something useful immediately?</p>
</li>
<li><p>Are clicks and scrolls smooth?</p>
</li>
<li><p>Do transitions feel instant?</p>
</li>
</ul>
<p>Performance is a <strong>perceived experience</strong>. You can score a 95 on Lighthouse and still feel slow if the first contentful paint doesn’t show something useful.</p>
<h2 id="heading-2-architecture-is-the-foundation-of-performance">2. <strong>Architecture is the Foundation of Performance</strong></h2>
<p>Great performance starts with <strong>how you structure your app.</strong></p>
<p>That means picking the right rendering strategy:</p>
<ul>
<li><p><strong>SSR</strong> for dynamic content with SEO</p>
</li>
<li><p><strong>SSG/ISR</strong> for speed at scale</p>
</li>
<li><p><strong>SPA</strong> for simple flows (but lazy-load carefully)</p>
</li>
</ul>
<p>Also consider:</p>
<ul>
<li><p>Server components (in React 19+)</p>
</li>
<li><p>Edge rendering with Vercel or Cloudflare</p>
</li>
<li><p>CDN-first asset and data delivery</p>
</li>
</ul>
<p><strong>Performance should be baked into your system design—not patched later.</strong></p>
<h2 id="heading-3-audit-before-you-act">3. <strong>Audit Before You Act</strong></h2>
<p>Performance tuning without data is like fixing a car with a blindfold on.</p>
<p>Here are my go-to tools:</p>
<ul>
<li><p><strong>Chrome DevTools</strong> – Performance tab + Lighthouse</p>
</li>
<li><p><a target="_blank" href="http://WebPageTest.org"><strong>WebPageTest.org</strong></a> – for real-world scenarios</p>
</li>
<li><p><strong>Next.js built-in analytics</strong></p>
</li>
<li><p><code>next/web-vitals</code> – to measure real user metrics</p>
</li>
<li><p>React Profiler – for rendering issues</p>
</li>
</ul>
<p>Always benchmark before and after changes.</p>
<h2 id="heading-4-modern-tools-give-you-superpowers">4. <strong>Modern Tools Give You Superpowers</strong></h2>
<p>We’re no longer in the 2015 jQuery days. Most frameworks today come with performance baked in—you just have to use them right.</p>
<h3 id="heading-if-youre-using-nextjs">If you're using Next.js:</h3>
<ul>
<li><p><code>next/image</code> handles image optimization</p>
</li>
<li><p><code>app/</code> directory with server components = less JS sent to client</p>
</li>
<li><p>API routes can run at the edge</p>
</li>
<li><p>Automatic static optimization with ISR</p>
</li>
</ul>
<p><strong>Don’t fight the framework—leverage it.</strong></p>
<h2 id="heading-5-optimize-the-critical-path">5. <strong>Optimize the Critical Path</strong></h2>
<p>Once your architecture is sound, optimize what matters most to perceived speed.</p>
<h3 id="heading-images">Images:</h3>
<ul>
<li><p>Use <code>next/image</code>, WebP or AVIF</p>
</li>
<li><p>Compress + lazy-load images</p>
</li>
<li><p>CDN delivery for fast loading</p>
</li>
</ul>
<h3 id="heading-fonts">Fonts:</h3>
<ul>
<li><p>Use system fonts where possible</p>
</li>
<li><p>Subset and self-host if using custom fonts</p>
</li>
<li><p>Add <code>font-display: swap</code> for instant rendering</p>
</li>
</ul>
<h3 id="heading-javascript">JavaScript:</h3>
<ul>
<li><p>Avoid huge bundles (tree-shake!)</p>
</li>
<li><p>Use dynamic imports for code splitting</p>
</li>
<li><p>Drop bloated libraries (e.g., moment.js → day.js)</p>
</li>
</ul>
<h3 id="heading-css">CSS:</h3>
<ul>
<li><p>Purge unused styles</p>
</li>
<li><p>Use Tailwind or CSS modules</p>
</li>
<li><p>Minimize layout shifts from animations</p>
</li>
</ul>
<h2 id="heading-6-understand-and-control-renders">6. <strong>Understand and Control Renders</strong></h2>
<p>React and Vue apps often suffer from unnecessary re-renders.</p>
<p>Be intentional:</p>
<ul>
<li><p>Use <code>React.memo</code>, <code>useMemo</code>, and <code>useCallback</code></p>
</li>
<li><p>Flatten your component tree</p>
</li>
<li><p>Avoid lifting state too high</p>
</li>
<li><p>Profile components with the DevTools</p>
</li>
</ul>
<p>Sometimes switching to <strong>Zustand</strong>, <strong>Jotai</strong>, or <strong>Signals</strong> can massively reduce render frequency compared to Context or Redux.</p>
<h2 id="heading-7-dont-forget-network-backend">7. <strong>Don’t Forget Network + Backend</strong></h2>
<p>A blazing-fast frontend can still feel slow if the backend is lagging.</p>
<ul>
<li><p>Use <strong>API caching</strong> with stale-while-revalidate strategies</p>
</li>
<li><p>Use <strong>GraphQL persisted queries</strong> to reduce overfetching</p>
</li>
<li><p>Minimize client-side waterfall requests</p>
</li>
<li><p>Deliver static content and JSON via CDNs</p>
</li>
</ul>
<p><strong>Frontend performance is full-stack.</strong></p>
<h2 id="heading-8-build-a-performance-culture">8. <strong>Build a Performance Culture</strong></h2>
<p>The best engineering teams don’t fix performance once—they bake it into how they build.</p>
<ul>
<li><p>Add Lighthouse checks to your CI/CD pipeline</p>
</li>
<li><p>Track web vitals with tools like Vercel Analytics or Datadog RUM</p>
</li>
<li><p>Set performance budgets</p>
</li>
<li><p>Make performance a KPI alongside features and design</p>
</li>
</ul>
<p>Performance shouldn’t be an afterthought—it should be part of your definition of done.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>In 2025, web performance isn’t a niche skill—it’s a competitive edge.</p>
<p>As engineers, we owe it to our users and our teams to build experiences that are not just functional, but fast, responsive, and delightful.</p>
<p>Because performance isn’t just about the code—it’s about how people feel when they use what you built.</p>
<hr />
<p><strong>What performance practice changed how you build apps? Let’s trade tips in the comment</strong></p>
]]></content:encoded></item><item><title><![CDATA[Mastering Redux Toolkit: A Step-by-Step Tutorial for New Developers.]]></title><description><![CDATA[In the world of building large applications, one of the biggest challenges, especially for teams of developers, is managing the state. While the Context API is useful, it has its limits, especially for applications with many features. To address this...]]></description><link>https://blog.calebbenjamin.com/mastering-redux-toolkit-a-step-by-step-tutorial-for-new-developers</link><guid isPermaLink="true">https://blog.calebbenjamin.com/mastering-redux-toolkit-a-step-by-step-tutorial-for-new-developers</guid><category><![CDATA[Redux Toolkit, shopping cart project, step-by-step guide, code examples, state management, React, web development.]]></category><category><![CDATA[Front-end development JavaScript Stateful applications Stateful components State management library State container State management patterns Immutable data Reducers Actions React components React state UI components Web development frameworks Front-end frameworks]]></category><dc:creator><![CDATA[Caleb Benjamin]]></dc:creator><pubDate>Sat, 22 Apr 2023 21:46:21 GMT</pubDate><content:encoded><![CDATA[<p>In the world of building large applications, one of the biggest challenges, especially for teams of developers, is managing the state. While the Context API is useful, it has its limits, especially for applications with many features. To address this, several state management tools have been introduced, but Redux has emerged as a leading solution.</p>
<p>It is worth noting that Redux is not part of ReactJS, despite being frequently used together. While Redux solves many problems, it also introduces new challenges. Setting up a Redux store and writing reducers can be a cumbersome and error-prone process that involves a lot of boilerplate code and manual configuration. This is where the Redux Toolkit comes in - the creators of Redux recognized the need for a more opinionated approach to setting up Redux applications, resulting in the development of the Redux Toolkit, which can be thought of as Redux with batteries included.</p>
<p>The Redux Toolkit eliminates the need for additional libraries and configurations, speeding up the workflow significantly. With the Redux Toolkit, users can benefit from Redux without having to deal with manual setups.</p>
<p>This article will cover all the essential building blocks of the Redux Toolkit. Specifically, we will be developing a shopping cart application that allows users to add and remove items, displaying the total price of the items in their cart. We will explore many of the features of the Redux Toolkit, including Store, Slice, Reducers, and Action Creators.</p>
<h3 id="heading-what-we-will-cover">What we will cover</h3>
<p>Setting up the Project<br />Installing Redux Toolkit<br />Creating the Redux Store<br />Setup Provider<br />Creating the Cart Slice<br />Creating the UI Components<br />Rendering the App<br />Running the App<br />Conclusion  </p>
<h3 id="heading-step-1-setting-up-the-project"><strong>Step 1: Setting up the Project</strong></h3>
<p>We will start by creating a new React project using Create React App. Open up your terminal and run the following command:</p>
<pre><code class="lang-bash">npx create-react-app shopping-cart
</code></pre>
<p>Once the project is created, navigate to the project directory:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> shopping-cart
</code></pre>
<h3 id="heading-step-2-installing-redux-toolkit"><strong>Step 2: Installing Redux Toolkit</strong></h3>
<p>Next, we need to install Redux Toolkit. Run the following command in your terminal:</p>
<pre><code class="lang-bash">npm install @reduxjs/toolkit react-redux
</code></pre>
<p>This will install the latest version of Redux Toolkit and add it to our project dependencies. Redux can be used for any frontend framework and is not specific to react, so in order to connect our Redux with react this is where the <code>react-redux</code> comes in.</p>
<p><strong>Just a side note:</strong> When we install <code>@reduxjs/toolkit</code> we actually installed a few libraries which are:</p>
<pre><code class="lang-markdown"><span class="hljs-bullet">-</span> redux (core library, state management)
<span class="hljs-bullet">-</span> immer (which allow us to mutate the state)
<span class="hljs-bullet">-</span> redux-thunk (which will handles the async actions)
<span class="hljs-bullet">-</span> reselect (which will simplifies the reducer functions)
</code></pre>
<p>All these will make sense if you have worked with Redux, but if you haven't worked with Redux before don't worry I will explain all of those as we go.</p>
<p>As an extra, we also get:</p>
<pre><code class="lang-markdown"><span class="hljs-bullet">-</span> redux devtools
<span class="hljs-bullet">-</span> combine reducers
</code></pre>
<h3 id="heading-step-3-creating-the-redux-store"><strong>Step 3: Creating the Redux Store</strong></h3>
<p>You are going to think of the <strong>store</strong> as the entire state of your application.<br />Create a new file called <code>store.js</code> in the <code>src</code> directory and add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { configureStore } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>; 
<span class="hljs-keyword">import</span> cartReducer <span class="hljs-keyword">from</span> <span class="hljs-string">'./features/cart/cartSlice'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> configureStore({ 
    <span class="hljs-attr">reducer</span>: { 
        <span class="hljs-attr">cart</span>: cartReducer, 
    }, 
});
</code></pre>
<p>This code imports the <code>configureStore</code> function from Redux Toolkit and our <code>cartReducer</code> from a file that we will create in the next step. It then exports the configured Redux store.</p>
<h3 id="heading-step-4-setup-provider"><strong>Step 4: Setup Provider</strong></h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;

<span class="hljs-comment">// import store and provider</span>
<span class="hljs-keyword">import</span> { store } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store'</span>;
<span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;

ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Provider</span> <span class="hljs-attr">store</span>=<span class="hljs-string">{store}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Provider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre>
<p>Next, we import the <strong>store</strong> and <strong>Provider</strong> and then wrap the entire application with the <em>Provider</em> and pass the <em>store</em> as props.</p>
<h3 id="heading-step-5-creating-the-cart-slice"><strong>Step 5: Creating the Cart Slice</strong></h3>
<p>I want you to think of <strong>slice</strong> as the features of your application for example increasing and decreasing the number of items in the cart or triggering a modal. The bigger the application the more features we are going to have. And in the <strong>Redux toolkit</strong> land, it is called <strong>slice.</strong></p>
<p>To setup a slice, a common convention is to create a <strong><em>features</em></strong> folder, Create a new directory called <code>features</code> in the <code>src</code> directory, and inside it, create a new directory called <code>cart</code>. Inside the <code>cart</code> directory, create a new file called <code>cartSlice.js</code> and add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSlice } <span class="hljs-keyword">from</span> <span class="hljs-string">'@reduxjs/toolkit'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> cartSlice = createSlice({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'cart'</span>,
  <span class="hljs-attr">initialState</span>: [],
  <span class="hljs-attr">reducers</span>: {
    <span class="hljs-attr">addToCart</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === action.payload.id);
      <span class="hljs-keyword">if</span> (index !== <span class="hljs-number">-1</span>) {
        state[index].quantity += <span class="hljs-number">1</span>;
      } <span class="hljs-keyword">else</span> {
        state.push({ ...action.payload, <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span> });
      }
    },
    <span class="hljs-attr">removeFromCart</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === action.payload);
      <span class="hljs-keyword">if</span> (index !== <span class="hljs-number">-1</span>) {
        state.splice(index, <span class="hljs-number">1</span>);
      }
    },
    <span class="hljs-attr">incrementQuantity</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === action.payload);
      <span class="hljs-keyword">if</span> (index !== <span class="hljs-number">-1</span>) {
        state[index].quantity += <span class="hljs-number">1</span>;
      }
    },
    <span class="hljs-attr">decrementQuantity</span>: <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> index = state.findIndex(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item.id === action.payload);
      <span class="hljs-keyword">if</span> (index !== <span class="hljs-number">-1</span>) {
        state[index].quantity -= <span class="hljs-number">1</span>;
        <span class="hljs-keyword">if</span> (state[index].quantity === <span class="hljs-number">0</span>) {
          state.splice(index, <span class="hljs-number">1</span>);
        }
      }
    },
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> { addToCart, removeFromCart, incrementQuantity, decrementQuantity } = cartSlice.actions;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> cartSlice.reducer;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectCart = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.cart;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> selectCartTotal = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> state.cart.reduce((total, item))
</code></pre>
<p>Let's understand what's happening in the code above.<br />The cartSlice.js contains the initial state of an empty array and several reducer functions for adding, removing, and updating items in the cart.</p>
<p>The <code>addToCart</code> reducer function checks if the item being added already exists in the cart by checking if its <code>id</code> matches any existing items in the cart. If it does, it increments the <code>quantity</code> of that item. If not, it adds the new item to the cart with a <code>quantity</code> of 1.</p>
<p>The <code>removeFromCart</code> reducer function removes an item from the cart by finding the index of the item with the <code>id</code> that matches the <code>payload</code> of the action being dispatched. If the item is found, it is removed from the cart using the <code>splice</code> method.</p>
<p>The <code>incrementQuantity</code> reducer function increments the <code>quantity</code> of an item in the cart by finding the index of the item with the <code>id</code> that matches the <code>payload</code> of the action being dispatched and incrementing its <code>quantity</code>.</p>
<p>The <code>decrementQuantity</code> reducer function decrements the <code>quantity</code> of an item in the cart by finding the index of the item with the <code>id</code> that matches the <code>payload</code> of the action being dispatched and decrementing its <code>quantity</code>. If the <code>quantity</code> of the item becomes 0, the item is removed from the cart using the <code>splice</code> method.</p>
<p>The <code>cartSlice.actions</code> object exports the four reducer functions defined in the <code>reducers</code> property of the <code>createSlice</code> function.</p>
<p>The <code>selectCart</code> and <code>selectCartTotal</code> functions are selectors that are used to access the <code>cart</code> slice of the Redux store and compute the total price of all items in the cart.</p>
<p>Finally, the <code>export default</code> statement exports the <code>cartSlice.reducer</code> function, which is used to create the Redux store for the shopping cart.</p>
<p>Overall, this code defines the structure and behavior of the shopping cart slice.</p>
<h3 id="heading-step-5-creating-the-ui-components"><strong>Step 5: Creating the UI Components</strong></h3>
<p>Now that we have our Redux store and <code>cartSlice</code> set up, we can start building the UI components for our shopping cart application. In the <code>src</code> directory, create a new directory called <code>components</code>. Inside the <code>components</code> directory, create a new file called <code>Cart.js</code> and add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useSelector, useDispatch } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-redux'</span>;
<span class="hljs-keyword">import</span> {
  selectCart,
  selectCartTotal,
  addToCart,
  removeFromCart,
  incrementQuantity,
  decrementQuantity,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'../features/cart/cartSlice'</span>;

<span class="hljs-keyword">const</span> Cart = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> cart = useSelector(selectCart);
  <span class="hljs-keyword">const</span> total = useSelector(selectCartTotal);
  <span class="hljs-keyword">const</span> dispatch = useDispatch();

  <span class="hljs-keyword">const</span> handleAddToCart = <span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
    dispatch(addToCart(item));
  };

  <span class="hljs-keyword">const</span> handleRemoveFromCart = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    dispatch(removeFromCart(id));
  };

  <span class="hljs-keyword">const</span> handleIncrementQuantity = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    dispatch(incrementQuantity(id));
  };

  <span class="hljs-keyword">const</span> handleDecrementQuantity = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    dispatch(decrementQuantity(id));
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Shopping Cart<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      {cart.length === 0 ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Your cart is empty.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
            {cart.map(item =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleRemoveFromCart(item.id)}&gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleIncrementQuantity(item.id)}&gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>${item.price * item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Total: ${total}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      )}

      &lt;button onClick={<span class="hljs-function">() =&gt;</span> handleAddToCart({ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Item 1'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">10</span> })}&gt;Add Item <span class="hljs-number">1</span> to Cart&lt;/button&gt;
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleAddToCart({ id: 2, name: 'Item 2', price: 20 })}&gt;Add Item 2 to Cart<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Cart;
</code></pre>
<p>This code defines a <code>Cart</code> the component that uses the <code>useSelector</code> and <code>useDispatch</code> hooks from React Redux to access the <code>cart</code> state and dispatch actions to the Redux store. It also defines several event handlers for adding and removing items from the cart and updating item quantities.</p>
<h3 id="heading-step-6-rendering-the-app"><strong>Step 6: Rendering the App</strong></h3>
<p>Finally, we need to render our <code>Cart</code> component in our <code>App</code> component. Open up the <code>App.js</code> file in the <code>src</code> directory and replace the existing code with the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> Cart <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Cart'</span>;

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>This code simply renders our <code>Cart</code> component in the <code>App</code> component.</p>
<h3 id="heading-step-7-running-the-app"><strong>Step 7: Running the App</strong></h3>
<p>With our project setup and our code written, we can now run our shopping cart application. Open up your terminal and run the following command:</p>
<pre><code class="lang-javascript">npm start
</code></pre>
<p>This will start the development server and open up the shopping cart application in your browser.  </p>
<h3 id="heading-ia"> </h3>
<p><strong>Conclusion</strong></p>
<p>In this article, we learned how to use Redux Toolkit to simplify the process of creating a Redux store and how to build a shopping cart application using React and Redux Toolkit. We created a <code>cartSlice</code> that contained the reducer, actions, and selectors</p>
]]></content:encoded></item><item><title><![CDATA[5 reasons why you need to start writing Test-driven development (TDD)]]></title><description><![CDATA[Writing tests for your app helps to ensure that your code is functioning correctly and is free of bugs. This improves the overall quality of your app, making it more reliable and user-friendly.
1. Improve code quality:
Writing tests for your app help...]]></description><link>https://blog.calebbenjamin.com/5-reasons-why-you-need-to-start-writing-test-driven-development-tdd</link><guid isPermaLink="true">https://blog.calebbenjamin.com/5-reasons-why-you-need-to-start-writing-test-driven-development-tdd</guid><category><![CDATA[Testing]]></category><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[react testing library]]></category><category><![CDATA[test driven development]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Caleb Benjamin]]></dc:creator><pubDate>Sun, 22 Jan 2023 10:27:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674382662305/823207d0-837e-46ab-bf96-1e9782dbefa3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Writing tests for your app helps to ensure that your code is functioning correctly and is free of bugs. This improves the overall quality of your app, making it more reliable and user-friendly.</p>
<h3 id="heading-1-improve-code-quality">1. Improve code quality:</h3>
<p>Writing tests for your app helps to ensure that your code is functioning correctly and is free of bugs. This improves the overall quality of your app, making it more reliable and user-friendly. writing test also helps you write cleaner, more maintainable code by ensuring that each piece of functionality is thoroughly tested and working as intended. Making it more reliable and stable.</p>
<h3 id="heading-2-fast-development">2. Fast Development:</h3>
<p>TDD allows you to write code faster by breaking it down into smaller, testable chunks. This helps you focus on one piece of functionality at a time, rather than trying to tackle a whole project all at once. By writing tests, you can quickly identify issues and bugs in their code, allowing them to fix them more quickly. This can help to speed up the development process and get your app to market faster.</p>
<h3 id="heading-3-better-scalability">3. Better Scalability:</h3>
<p>Test help to ensure that your code can handle increasing amounts of data and users. This is important for apps that are expected to grow in popularity and usage, as it ensures that they can handle the increased demand.</p>
<h3 id="heading-4-better-documentation">4. Better Documentation:</h3>
<p>TDD helps you document your code by providing a clear and concise description of how each piece of functionality is supposed to work. They can make it easier for others to understand and maintain your code, even if they are not familiar with the specific language or framework you are using.</p>
<h3 id="heading-5-more-robust-code">5. More Robust Code:</h3>
<p>TDD helps you write more robust code by catching errors and bugs early on in the development process. This can help you avoid costly and time-consuming bugs that can be difficult to fix later on. Additionally, TDD can you help you identify edge cases and potential issues that you may no have thought of otherwise, helping you write more resilient code that can handle unexpected situations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Please let me know more reasons why we need TDD in the comments section below. I'll had like to know your reasons as well so I can pass them on to other developers like myself.😊</p>
]]></content:encoded></item><item><title><![CDATA[10 Advance React Do's and Don'ts]]></title><description><![CDATA[Learning is a never-ending journey, as a developer you must learn to un-learn and re-learn new things every day. It should be a norm as developers to search google for best practices so we can write clean, scalable, and maintainable code and also be ...]]></description><link>https://blog.calebbenjamin.com/10-advance-react-dos-and-donts</link><guid isPermaLink="true">https://blog.calebbenjamin.com/10-advance-react-dos-and-donts</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[context API]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Caleb Benjamin]]></dc:creator><pubDate>Thu, 06 Oct 2022 07:21:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665040146893/MuauECFdt.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Learning is a never-ending journey, as a developer you must learn to un-learn and re-learn new things every day. It should be a norm as developers to search google for best practices so we can write clean, scalable, and maintainable code and also be productive. In this article I will show you 10 react do's and don'ts, to help you start building optimizable production-ready applications when using react.</p>
<p><strong>NOTE:</strong> <em>These are my personal preference from my 5years of writing react, I hope these help you become a better react developer or javascript engineer in general.</em></p>
<h3 id="heading-what-you-will-learn">📚What you will learn</h3>
<p> <strong>The DOs</strong></p>
<ul>
<li>Use TypeSctript</li>
<li>Use a query library</li>
<li>Learn to make custom hooks</li>
<li>Learn to get used to dependency arrays</li>
<li>Use functional components over class components</li>
<li>Use Next.js for server-side rendering and Gatsby for static websites</li>
</ul>
<p><strong>The DON'Ts</strong></p>
<ul>
<li>Don't use React Fragment</li>
<li>Don’t make your own UI library</li>
<li>Don’t ignore useCallback or useMemo</li>
<li>Don’t use Redux just because you think you have to</li>
</ul>
<h2 id="heading-the-dos">The DOs</h2>
<h3 id="heading-use-typesctript">🎯Use TypeSctript</h3>
<p>Use Typescript when building your react app, it helps you make more robust, reliable, and easy to maintain applications. So why are you not using TS in your react app? it has saved me so many times from run-time errors and I have only been using it for a year now. TypeScript is absolutely worth using in your react app.</p>
<h3 id="heading-use-a-query-library">🎯Use a query library</h3>
<p>Speaking of query libraries I highly recommend you use them. Use something like  <strong>React-Query,</strong> <strong>SWR</strong> - these are fantastic query libraries that do more than just fetching, they give you a lot right out of the box. They allow fetching, caching, or re-fetching data in real-time, and re-fresh on an interval. They also have useMutation that makes it possible to do post requests and is super simple. My strong recommendation to you is to use them if you want to access any API.</p>
<h3 id="heading-learn-to-make-custom-hooks">🎯Learn to make custom hooks</h3>
<p>Do learn to make and use your own custom hooks. Custom hooks are collections of hooks gathered together as a function that accomplishes a specific task.</p>
<h3 id="heading-learn-to-get-used-to-dependency-arrays">🎯Learn to get used to dependency arrays</h3>
<p>Learn to love dependency arrays, at least deal with them, or don't hate them quite so much 😊. So dependency arrays are the arrays at the end of useEffect, useCallback, and useMemo, and they tell react when a useEffect should run if any of the items in that dependency array change then your useEffect will re-run, and useEffect is the one that gives people more grief. </p>
<p><strong>Here are some rules to help you </strong></p>
<ul>
<li><strong>Rule #1</strong>  Add anything you read from that array</li>
<li><strong>Rule #2</strong>  Check what you write in the dependency array</li>
<li><strong>Rule #3</strong>  Don't disable the lint-rule</li>
</ul>
<h3 id="heading-use-functional-components-over-class-components">🎯Use functional components over class components</h3>
<p>Don't use class components, but if you are still using class components or you are new to React, I highly recommend starting with the functional component. Let me give you some reasons.</p>
<ol>
<li><p>Functional Components are the future of React, take a look at their <a href="https://reactjs.org">documentation site</a> where is really hard to find a class component, even on their new <a href="https://beta.reactjs.org">beta site</a> is nearly impossible to find a class component, why does it make sense? </p>
</li>
<li><p>Functional Component has a better state mechanism than class-based components. Functional components use hooks and those hooks create reactive state management baked right in to react. Using useState and useReducer you can declare your state, and then using useEffect and useCallback and useMemo you react to changes in the state. Those 5 little hooks can create an amazing ecosystem of super awesome hooks. There are hooks for calling an API, for doing external state management, for CSS, Animations, and everything you can think of has a hook. You won't get access to any of that if you are using class components.</p>
</li>
<li><p>Is harder to build applications with functional components and hooks, there's a deeper learning curve, so if you start it is pretty easy to fall back to class-based components if you find yourself on a project that uses them.</p>
</li>
</ol>
<p>If you are just starting out and you are currently learning class-based components, I highly recommend using functional-based components.</p>
<h3 id="heading-use-nextjs-for-server-side-rendering">🎯Use Next.js for server-side rendering</h3>
<p>I will highly recommend you use Next.js instead of pure react. If you are concerned about the SEO in your application then go with next.js. 
Next.js gives you the best developer experience with all the features you need for production: hybrid static &amp; server rendering, TypeScript support, smart bundling, route pre-fetching, and more. No config is needed.</p>
<h2 id="heading-the-donts">The DON'Ts</h2>
<h3 id="heading-dont-use-react-fragment">🎯Don't use React Fragment</h3>
<p>Don't use React Fragment, This causes increased DOM depth causing DOM manipulation slower.</p>
<h3 id="heading-dont-make-your-own-ui-library">🎯Don’t make your own UI library</h3>
<p>Here is the one that's so dear to my heart, Don't build your own UI library, react has an amazing ecosystem of UI libraries, there is MaterialUI, Bootstrap, Auntd, Tailwind, ChakraUI, and Mantine. These are fantastic UI libraries that come out of the box with most of the components you will be needing, plus they are scalable, themeable, and internationalizable. They have great documentation and a whole user community around them that make it very easy to use them.
Most importantly some of these libraries, particularly MateriaUI come with templates for a lot of designers' favorite tools like Figma. There's a Figma template for material-UI and it is great at what it does, it allows designers to specify the UI for a component by just dragging and dropping it, and those mockups are exact. I think is just a much better way to communicate with the design team and the development team. You will lose all these if you build your own UI library.</p>
<h3 id="heading-dont-ignore-usecallback-or-usememo">🎯Don’t ignore useCallback or useMemo</h3>
<p>Don't ignore useCallback or useMemo. Some advice that went around about how useCallback and useMemo impact the performance of a react app, but that is not 100% true. Yes, they are vital to the reactive state management for react, and when used properly to retain referential identity, it can be a performance enhancement to your react app. Let's take a look at the two hooks and their few use case.</p>
<ul>
<li><strong>useMemo:</strong>  is used if you are computing an array or an object because those are maintained by reference and you want to maintain that referential identity. </li>
<li><strong>useCallback:</strong> is used in two cases.  <strong>1.</strong> is where you want to keep your callback function from being stale. and  <strong>2.</strong> is when you want to retain the referential identity of those callbacks.</li>
</ul>
<h3 id="heading-dont-use-redux-just-because-you-think-you-have-to">🎯Don’t use Redux just because you think you have to</h3>
<p>When you are thinking about building out your applications and you are thinking about choosing your state management model, my recommendation to you is to start with React state management (Context and Hooks) and see how far that can take you, they may actually be enough. If not enough then go for API requests and use query libraries like React-Query, and SWR. These are strong state management with their caches that might be enough, with a combination of React-Context plus React-Query, and SWR. If you're doing forms then use form libraries like React-Hook-Form or Formik which also maintain state. The combination of all these hooks might be enough for a state management system for your application. But if that doesn't do it then you can use Redux or ReduxToolKit.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>How did I do? did I get your own Dos? did I get your own Don'ts?
Please let me know in the comments section below. I'll had like to know what dos and don'ts you have to pass on to other react developers like myself.😊</p>
]]></content:encoded></item><item><title><![CDATA[5 important features you must master in CSS]]></title><description><![CDATA[Introduction
Hello Guys, in this article you are going to know the 5 CSS properties and features you need to master, once you master these features I assure you that you can be able to build any UI design that comes your way, from basic to advance de...]]></description><link>https://blog.calebbenjamin.com/5-important-features-you-must-master-in-css</link><guid isPermaLink="true">https://blog.calebbenjamin.com/5-important-features-you-must-master-in-css</guid><category><![CDATA[Frontend Development]]></category><category><![CDATA[CSS]]></category><category><![CDATA[flexbox]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Caleb Benjamin]]></dc:creator><pubDate>Tue, 04 Oct 2022 09:40:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664838197952/qt3E9UyDM.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Hello Guys, in this article you are going to know the 5 CSS properties and features you need to master, once you master these features I assure you that you can be able to build any UI design that comes your way, from basic to advance designs.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>This article is for total beginners and for intermediate-level developers that want to sharpen their skills in CSS.</p>
<h3 id="heading-what-you-will-learn">What you will learn</h3>
<ul>
<li>What is CSS</li>
<li>Margin and Padding<ul>
<li>Use case</li>
<li>Helpful resources </li>
</ul>
</li>
<li>Positioning<ul>
<li>Types of Positioning</li>
<li>Helpful resources </li>
</ul>
</li>
<li>Flexbox?<ul>
<li>Features of flexbox</li>
<li>Flexbox properties</li>
</ul>
</li>
<li>CSS Grid<ul>
<li>Helpful resources</li>
</ul>
</li>
<li>Media Queries<ul>
<li>Helpful resources</li>
</ul>
</li>
</ul>
<h3 id="heading-what-is-css">What is CSS?</h3>
<p>CSS stands for Cascading Style Sheet, and it is simply used to style web pages.
CSS has over 259 properties used for styling and in all these large numbers of properties, there are few that are used on a daily bases, and without them, we can't build a standard design. </p>
<p>These few CSS properties are:</p>
<ul>
<li>Margin &amp; Padding</li>
<li>Positioning</li>
<li>Flexbox</li>
<li>Grid</li>
<li>Media Queries</li>
</ul>
<h3 id="heading-margin-amp-padding">Margin &amp; Padding</h3>
<p>Understanding how margin and padding work is very simple and important.
Margin is the space around all HTML elements, While Padding is the space inside the HTML elements.</p>
<h4 id="heading-use-cases">Use cases</h4>
<p>You can use a margin to ensure that other elements aren't too close to the element in question. You can use padding to make space inside the element itself.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1664274330491/E3zuoHN_9.png" alt="Screenshot (127).png" /></p>
<h4 id="heading-helpful-rescourse">Helpful rescourse</h4>
<p><a href="https://www.youtube.com/watch?v=EhbZGV2dqZ4">Margin and Padding Deep Dive: The basics</a></p>
<p><a href="https://www.youtube.com/watch?v=NZEz4yNITd8">How CSS Padding and Margin Works</a></p>
<h3 id="heading-positioning">Positioning</h3>
<p>Positioning an element is another important feature in CSS, positioning will help you achieve some cool design patterns when designing. 
The CSS position property defines the position of an HTML element in a document. This property works with the left, right, top, bottom, and z-index properties to determine the final position of an element on a page.
Note that by default, the position property for all HTML elements in CSS is set to static. This means that if you don't specify any other position value or if the position property is not declared explicitly, it'll be static</p>
<h4 id="heading-types-of-positioning">Types of Positioning</h4>
<ul>
<li>Position Relative</li>
<li>Position Absolute</li>
<li>Position Fixed</li>
<li>Position Sticky</li>
<li>Position Static</li>
</ul>
<h4 id="heading-helpful-resources">Helpful resources</h4>
<p><a href="https://www.youtube.com/watch?v=gD3G67oPg-w">CSS Position Tutorial | Learn CSS For Beginners</a></p>
<p><a href="https://www.youtube.com/watch?v=P6UgYq3J3Qs">CSS Positioning: Position absolute and relative explained</a></p>
<h3 id="heading-flexbox">Flexbox</h3>
<p>The flexbox or flexible box model in CSS is another key feature to master, it is a layout model that provides an easy and clean way to arrange items within a container. Flexbox can be useful for creating small-scale layouts &amp; is responsive and mobile-friendly.</p>
<h4 id="heading-features-of-flexbox">Features of flexbox:</h4>
<ul>
<li>A lot of flexibility is given.</li>
<li>Arrangement &amp; alignment of items.</li>
<li>Proper spacing</li>
<li>Order &amp; Sequencing of items.</li>
</ul>
<h4 id="heading-flexbox-properties">Flexbox properties:</h4>
<ul>
<li>Display: flex </li>
<li>Flex-direction: row | row-reverse | column | column-reverse</li>
<li>align-self: flex-start | flex-end | center | baseline | stretch</li>
<li>justify-content: start |  center | space-between | space-around | space-evenly</li>
</ul>
<h3 id="heading-helpful-resources">Helpful resources</h3>
<p><a href="https://web.dev/learn/css/flexbox/">Introduction to Flexbox</a></p>
<p><a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/">A Complete Guide to Flexbox</a></p>
<h3 id="heading-css-grid-layout">CSS Grid Layout</h3>
<p>CSS Grid is similar to flexbox but is more geared toward complex layouts, it can be used to create any kind of layout, and it is more complex and difficult to master.</p>
<h3 id="heading-helpful-resources">Helpful resources</h3>
<p><a href="https://css-tricks.com/snippets/css/complete-guide-grid/">A Complete Guide to Grid</a></p>
<p><a href="https://www.freecodecamp.org/news/learn-css-grid-by-building-5-layouts/">Learn CSS Grid by Building 5 Layouts in 17 minutes</a></p>
<h3 id="heading-media-queries">Media Queries</h3>
<p>You can't build a modern website if you don't understand what and how media query works. Media queries are a key part of responsive web design, as they allow you to create different layouts depending on the size of the viewport, but they can also be used to detect other things about the environment your site is running on, for example, whether the user is using a touchscreen rather than a mouse.</p>
<h4 id="heading-helpful-resources">Helpful resources</h4>
<p><a href="https://css-tricks.com/a-complete-guide-to-css-media-queries/">A Complete Guide to CSS Media Queries</a></p>
<p><a href="https://www.freecodecamp.org/news/css-media-queries-breakpoints-media-types-standard-resolutions-and-more/">Standard Resolutions, CSS Breakpoints, and Target Phone Sizes</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you can master those five CSS properties you can build any design that comes your way from your design team or your client. These properties come in handy in almost all standard projects you will come across. I hope you have found this article helpful.</p>
]]></content:encoded></item><item><title><![CDATA[HTTP-Only Cookies Authentication with Next.js]]></title><description><![CDATA[Greeting! folks, If you don't want to save your JWT token on the client side then I believe that's why you're here, So welcome. In this article am going to show you how to handle authentication, JWT & HttpOnly Cookies with Next.js. This example will ...]]></description><link>https://blog.calebbenjamin.com/http-only-cookies-authentication-with-nextjs</link><guid isPermaLink="true">https://blog.calebbenjamin.com/http-only-cookies-authentication-with-nextjs</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[authentication]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[React]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Caleb Benjamin]]></dc:creator><pubDate>Fri, 23 Sep 2022 18:53:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1663960245612/4OGR5n4hy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Greeting! folks, If you don't want to save your JWT token on the client side then I believe that's why you're here, So welcome. In this article am going to show you how to handle authentication, JWT &amp; HttpOnly Cookies with Next.js. This example will go with any API endpoints you are using. 
In order to follow along with the project, I create a starter project where all the styling is done so we can just focus on handling all the required Authentications in our application. You can grab it here <a target="_blank" href="https://github.com/calebbenjin/starter-jwtauth-nextjs">Starter files</a>  </p>
<h3 id="heading-what-were-going-to-cover">What We're Going To Cover</h3>
<ul>
<li>What Is JWT?</li>
<li>JSON Web Token Dos and Don't</li>
<li>Our JWT Strategy Explained</li>
<li>Cloning And Setting Up Our Project</li>
<li>Setting Up AuthContext</li>
<li>Login And Get JWT</li>
<li>Store JWT In Server HttpOnly Cookie</li>
<li>Persist Logged in User</li>
<li>Logout And Destroy Cookie</li>
<li>Register User</li>
</ul>
<h4 id="heading-what-is-jwt">What Is JWT?</h4>
<p>A JSON Web Token (JWT) is really just a way to transmit information between two parties. One party might be your frontend React application and another party might be your API. The real value of JSON Web Tokens is they include a security feature. That is you can be sure that the information that was transmitted in the token wasn't tampered with along the way.</p>
<h4 id="heading-json-web-token-dos-and-dont">JSON Web Token Dos And Don't</h4>
<p>I wanted to outline some do's and don'ts. Let's start with the don'ts.</p>
<ul>
<li>The first don't that I've got is don't store your tokens in Local Storage. The reason that it's risky to keep them in local storage is that local storage is easily scriptable.</li>
<li>The next don't that I've got is don't keep these secret keys that go into signing your tokens in the browser. The only place that you should be keeping your secret keys is on your backend, because browsers are public clients. Any time a user loads up a website or an application, they get all of the code that goes into powering that application.</li>
</ul>
<h5 id="heading-now-for-the-dos">Now for the Do's,</h5>
<p>Do keep long, strong, unguessable secrets. Keep something that is super long, strong, and unguessable.</p>
<h4 id="heading-our-jwt-strategy-explained">Our JWT Strategy Explained</h4>
<p>Now what we are going to do in our application is create an API routes within Nextjs which run on the server-side. We are going to have routes that we can hit, then from there we will make our request to the API Endpoint, get the token and then we will set the cookie on the server-side, what's called the Http-Only Cookie, that means it can't be accessed via the browser (local Storage) so that's a saver way to go. So let's dive into code and start to create our API routes.</p>
<h4 id="heading-cloning-and-setting-up-our-project">Cloning And Setting Up Our Project</h4>
<p>So like l said I have already created a starter files so Jump right in and clone it.</p>
<pre><code>https:<span class="hljs-comment">//github.com/calebbenjin/starter-jwtauth-nextjs</span>
</code></pre><p>After cloning the app, open it in your VScode and press <code>crtl+J</code> your terminal will open then type <code>yarn add or npm install</code> to install all necessary dependences. After that type <code>npm run dev or yarn run dev</code>: <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spbjd2y473sx5ucapqua.png" alt="Your app will look this" /></p>
<h4 id="heading-setting-up-authcontext">Setting Up AuthContext</h4>
<p>Now we want to create our context, we are going to use the Context-API, where we can store all our Authentication methods, our users and also any errors that comes from authentication.
So we are going to create a new folder in the <code>root</code> called <code>context</code> then inside the context we're going to create a file called <code>AuthContext.js</code>. </p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xhytgrcssktd0p78ksbn.png" alt="your application should look like this" /></p>
<p>So We want to basically create a context using <code>createContext</code> from react. So now go inside your <code>AuthContext</code> file and fill it with this code snippet below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useEffect, createContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/router'</span>
<span class="hljs-keyword">import</span> {NEXT_URL} <span class="hljs-keyword">from</span> <span class="hljs-string">'../config/index'</span>

<span class="hljs-keyword">const</span> AuthContext = createContext()

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AuthProvider = <span class="hljs-function">(<span class="hljs-params">{children}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>)
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>)
  <span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>)

  <span class="hljs-keyword">const</span> router = useRouter()

  <span class="hljs-comment">// Register user</span>
  <span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> ({ fullname, email, password }) =&gt; {
    setIsLoading(<span class="hljs-literal">true</span>)
    <span class="hljs-built_in">console</span>.log(fullname, email, password)
  }

  <span class="hljs-comment">// Login user</span>
<span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> ({email, password}) =&gt; {
  setIsLoading(<span class="hljs-literal">true</span>)
  <span class="hljs-built_in">console</span>.log(email, password)
}

  <span class="hljs-comment">// Logout user</span>
  <span class="hljs-keyword">const</span> logout = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"User Logged out"</span>)
  }

  <span class="hljs-comment">// Check if user id Logged in</span>
  <span class="hljs-keyword">const</span> checkedUserLoggedIn = <span class="hljs-keyword">async</span> (user) =&gt; {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Checked'</span>)
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AuthContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">register</span>, <span class="hljs-attr">login</span>, <span class="hljs-attr">logout</span>, <span class="hljs-attr">isLoading</span>, <span class="hljs-attr">user</span>, <span class="hljs-attr">error</span>}}&gt;</span>
      {children}
    <span class="hljs-tag">&lt;/<span class="hljs-name">AuthContext.Provider</span>&gt;</span></span>
  )
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AuthContext
</code></pre>
<p>Now let me explain the code above. We imported some necessary hooks from react like <code>{ useState, useEffect, createContext }</code> and also <code>{useRouter}</code> from <code>next/router</code>, Next we imported our <code>{API_URL}</code> this will be your API endpoint URL of choice. Next we create a context by creating a variable called <code>AuthContext</code> and set it to <code>createContext</code>.
Next we created a provider that needs to wrap around our application so we can provides certain functions to our application and whatever component needed. Next we created some state <code>[user, setUser]</code> and <code>[error, setError]</code> and we set the default to null. Next we created some methods like <code>register, login, logout, checkUserLoggedIn</code> which we will use to hit our backend routes. Then as you can see we are exposing all the methods created so it can be accessible all over the application. So let's do that by going into our <code>_app.js</code> file in the pages folder and bring in our <code>AuthProvider</code> as you can see below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'../styles/globals.css'</span>
<span class="hljs-keyword">import</span> Navbar <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/Navbar'</span>
<span class="hljs-keyword">import</span> {AuthProvider} <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AuthProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Navbar</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">AuthProvider</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyApp
</code></pre>
<h3 id="heading-login-andamp-get-jwt">Login &amp; Get JWT</h3>
<p>So in this section we are going to setup our login functionality and get the JWT token, we're not going to store it just yet but what we want to do is to create an <code>api-route</code> to connect to and in that <code>api-route</code> is were we are going to communicate with our backend-endpoint, we are going to send our request from there get the token and then our next step is to save the Http-Only Cookie. So let's dive right in by getting into our api folder and create a new file called <code>login.js</code> <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m13egb7eauy9gb6p7rls.jpg" alt="api-route folder" />
Now copy the code below and paste in the <code>login.js</code> file you have created, I will explain things in details below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { API_URL} <span class="hljs-keyword">from</span> <span class="hljs-string">'../config/index'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">if</span>(req.method === <span class="hljs-string">'POST'</span>) {

  } <span class="hljs-keyword">else</span> {
    res.setHeader(<span class="hljs-string">'Allow'</span>, [<span class="hljs-string">'POST'</span>])
    res.status(<span class="hljs-number">405</span>).json({<span class="hljs-attr">message</span>: <span class="hljs-string">`Method <span class="hljs-subst">${req.method}</span> not allowed`</span>})
  }
}
</code></pre>
<p>First we import our <code>API_URL</code> this can be your <code>api url of choice</code>
Next we create an <code>async</code> function and pass in our <code>(req res)</code>
Next we want to make sure if is the <code>req.method</code> is equal to <code>POST</code>, else we want to <code>res.setHeader('Allow', ['POST']</code> and set the status <code>res.status(405)</code> which is method not allowed and send a <code>.json({message:</code>Method ${req.method} not allowed<code>})</code>.
Next after making sure is a post request we want to get the email, and password from the <code>req.body</code> so we do that by destructuring the email and password from <code>req.body</code>. 
Now in this our <code>api route</code> this were we want to login our user with actual <code>backend api-endpoint</code> or l should say fetch our token. Now go ahead and paste the code below inside of your code.</p>
<pre><code class="lang-javascript">   <span class="hljs-comment">// destructure email, and password</span>
    <span class="hljs-keyword">const</span> { email, password } = req.body

    <span class="hljs-comment">// Making a post request to hit our backend api-endpoint</span>
    <span class="hljs-keyword">const</span> apiRes = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>/your url of choice`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        email,
        password
      })
    })

    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> apiRes.json()

    <span class="hljs-keyword">if</span>(apiRes.ok) {
      <span class="hljs-comment">// @todo - Set Cookie</span>

      res.status(<span class="hljs-number">200</span>).json({<span class="hljs-attr">user</span>: data.user})
    } <span class="hljs-keyword">else</span> {
      res.status(data.statusCode).json({<span class="hljs-attr">message</span>: data.message})
    }
</code></pre>
<p>So if you're following correctly your code show look like this below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { API_URL} <span class="hljs-keyword">from</span> <span class="hljs-string">'../config/index'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">if</span>(req.method === <span class="hljs-string">'POST'</span>) {
    <span class="hljs-keyword">const</span> { email, password } = req.body

    <span class="hljs-keyword">const</span> apiRes = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>/your url of choice`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        email,
        password
      })
    })

    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> apiRes.json()

    <span class="hljs-built_in">console</span>.log(data.jwt)

    <span class="hljs-keyword">if</span>(apiRes.ok) {
      res.status(<span class="hljs-number">200</span>).json({<span class="hljs-attr">user</span>: data.user})
    } <span class="hljs-keyword">else</span> {
      res.status(data.statusCode).json({<span class="hljs-attr">message</span>: data.message})
    }

  } <span class="hljs-keyword">else</span> {
    res.setHeader(<span class="hljs-string">'Allow'</span>, [<span class="hljs-string">'POST'</span>])
    res.status(<span class="hljs-number">405</span>).json({<span class="hljs-attr">message</span>: <span class="hljs-string">`Method <span class="hljs-subst">${req.method}</span> not allowed`</span>})
  }
}
</code></pre>
<p>So what we have done so far, which is creating this <code>api-endpoint</code> inside our Nextjs app, is like a middle man between our frontend and the backend-api, and then we are doing this so we can set <code>Http-Only Cookie</code> with token. 
You can <code>console.log(data.jwt)</code> to see it.
Next let's head over to <code>AuthContext</code> and go to the <code>login</code> method we create so we can make a request to our <code>api/login</code> api-endpoint we have created. So paste these code inside of the <code>login</code> function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${NEXT_URL}</span>/api/login`</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
      email,
      password
    })
  })

  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json()

  <span class="hljs-keyword">if</span>(res.ok) {
    setUser(data.user)
    router.push(<span class="hljs-string">'/dashboard'</span>)
  } <span class="hljs-keyword">else</span> {
    setError(data.message)
    setError(<span class="hljs-literal">null</span>)
  }
</code></pre>
<p>Now we are fetching the data from the api route we create in <code>api/login</code>. After that we check if the request is okay then we setUser(data.user) and make a redirect to our dashboard using <code>next/router</code>, But if is not <code>Ok</code> then we want to setError(data.message) and also setError(null) so the error will not remain in our state.
Next let's head on to our login page and bring in our login method from <code>AuthProvider</code>, so now update your login page with these code</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">import</span> AuthContext <span class="hljs-keyword">from</span> <span class="hljs-string">'../context/AuthContext'</span>

  <span class="hljs-keyword">const</span> { login, error, user, isLoading } = useContext(AuthContext)

  <span class="hljs-keyword">const</span> handleLoginSubmit = <span class="hljs-keyword">async</span> ({ email, password }) =&gt; {
    login({email, password})
  }
</code></pre>
<p>We are importing our AuthContext, then we destructure out <code>login, error, user, isLoading</code> from it. Then in our handleLoginSubmit function we then call in the <code>login({email, password})</code> and then pass in <code>email, and password</code>.
Now at this point our app should be working very fine, next we are going to go head and store our jwt in the server httpOnly Cookie. Let's dive in.</p>
<h3 id="heading-store-jwt-in-server-httponly-cookie">Store JWT In Server HttpOnly Cookie</h3>
<p>Now what we want to do is set the Cookies, there's quite a few ways to do this, but we are going to use a package called <code>cookie</code> that let's us easily set cookie on the server-side, if you check in our <code>package.json</code> file you will see that l have install it already, or you can install it @ <code>yard add cookie</code> or <code>npm install cookie</code> if you are not using the start file.
Next we going to bring in our <code>api/login.js</code> file </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> cookie <span class="hljs-keyword">from</span> <span class="hljs-string">'cookie'</span>
</code></pre>
<p>So go down the code where we have our <code>@todo Set Cookie</code> comment and add these code there.</p>
<pre><code class="lang-javascript">  res.setHeader(
    <span class="hljs-string">'Set-Cookie'</span>,
    cookie.serialize(<span class="hljs-string">'token'</span>, <span class="hljs-built_in">String</span>(apiRes.data.token), {
      <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">secure</span>: process.env.NODE_ENV !== <span class="hljs-string">'development'</span>,
      <span class="hljs-attr">maxAge</span>: <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">7</span>, <span class="hljs-comment">// 1 week</span>
      <span class="hljs-attr">sameSite</span>: <span class="hljs-string">'strict'</span>,
      <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>
    })
 )
</code></pre>
<p>Now as you can see we are setting res.setHeader that's coming with <code>'Set-Cookie'</code> and a second parameter of <code>cookie.serialize()</code> then we set the name of the cookie to be <code>cookie.serialize('token')</code> and the value is going to be <code>cookie.serialize('token', String(apiRes.data.token)</code> and we also have an object option which is the <code>httpOnly: true</code> and <code>secure</code> since is going to be https and we want that to be <code>true</code> on <code>production</code> not <code>development</code> then we are going to set it to <code>process.env.NODE_ENV !== 'development',</code> and also check the node environment and see if that's not equal to <code>development</code> if is equal to <code>development</code> then is going to be false, if is in <code>production</code> is going to be true. Then we do <code>maxAge</code> is set to a week <code>maxAge: 60 * 60 * 24 * 7, // 1 week</code>. then we set <code>sameSite</code> to strict and <code>path</code> is set to '/' because we want it to be accessible everywhere. So this will set the cookie on the server-side once we login our app.</p>
<h3 id="heading-persist-logged-in-user">Persist Logged in User</h3>
<p>Now we are going to persist the user and that is going to happen with the <code>checkUserLoggedIn</code> function we created in our <code>AuthContext</code>. Now this <code>checkUserLoggedIn</code> is going to hit a new route called <code>user</code> so go ahead and create a <code>user.js</code> file inside of our <code>api folder</code>. Basically what we are going to do in this <code>user.js</code> is to hit the users endpoint of your api, what we can do is we can send our token which we have in our cookie right now, once we send the token it will give you back the user for that token, then what we do with in <code>AuthContext</code> is set the <code>user</code>. Now go head and copy the code and paste in the <code>user.js</code> file you have created.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { API_URL } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/lib/index'</span>
<span class="hljs-keyword">import</span> cookie <span class="hljs-keyword">from</span> <span class="hljs-string">'cookie'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">if</span> (req.method === <span class="hljs-string">'GET'</span>) {
    <span class="hljs-keyword">if</span> (!req.headers.cookie) {
      res.status(<span class="hljs-number">403</span>).json({<span class="hljs-attr">message</span>: <span class="hljs-string">'Not Authorized'</span>})
      <span class="hljs-keyword">return</span>
    }

    <span class="hljs-keyword">const</span> { token } = cookie.parse(req.headers.cookie)

    <span class="hljs-keyword">const</span> apiRes = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>/user`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-attr">Authorization</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${token}</span>`</span>
      }
    })

    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> apiRes.json()

    <span class="hljs-keyword">if</span>(apiRes.ok) {
      res.status(<span class="hljs-number">200</span>).json({user})
    } <span class="hljs-keyword">else</span> {
      res.status(<span class="hljs-number">403</span>).json({<span class="hljs-attr">message</span>: <span class="hljs-string">'User forbidden'</span>})
    }
  } <span class="hljs-keyword">else</span> {
    res.setHeader(<span class="hljs-string">'Allow'</span>, [<span class="hljs-string">'POST'</span>])
    res.status(<span class="hljs-number">405</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">`Method <span class="hljs-subst">${req.method}</span> not allowed`</span> })
  }
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> user
</code></pre>
<p>Now inside our function we are first checking to see if the cookie exist <code>(!req.headers.cookie)</code> if that's not there then <code>res.status(403).json({message: 'Not Authorized'})</code> and then we <code>return</code>.
But if is found then we need to pass the cookie and get the token. we then destructure the  token <code>const { token } = cookie.parse(req.headers.cookie)</code> this will put the token into a variable and then we can send into our backend-Api. Once we get the user back. and then check if the apiRes.ok then we want to set the <code>status(200)</code> and send the user object. else the user is forbidden <code>res.status(403).json({message: 'User forbidden'})</code>.
Now let's save that and hit this api-route with <code>checkUserLoggedIn</code>. now let's go to our <code>AuthContext</code> and fill in out <code>checkUserLoggedIn</code> with this code, just a simple get request</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> checkUserLoggedIn = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${NEXT_URL}</span>/api/user`</span>)
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json()

    <span class="hljs-keyword">if</span> (res.ok) {
      setUser(data.user.data.user)
    } <span class="hljs-keyword">else</span> {
      setUser(<span class="hljs-literal">null</span>)
    }
  }
</code></pre>
<p>Now we are checking that if everything goes ok then we're setting <code>setUser(data.user.data.user)</code> the user we get back from our <code>backend-api</code> else we are going to <code>setUser</code> to <code>null</code> and then we want to call this up here in a <code>useEffect</code> so let's go under our state and call the useEffect. </p>
<pre><code class="lang-javascript">  useEffect(<span class="hljs-function">() =&gt;</span> checkUserLoggedIn(), [])
</code></pre>
<h3 id="heading-logout-and-destroy-cookie">Logout And Destroy Cookie</h3>
<p>Now we are going to have another api route for this because we need to destroy the cookie that's going to happened in our server which in our api route. So let's create a <code>logout.js</code> in our api folder. after we have done that, go ahead and paste the code inside of the <code>logout.js</code> file we just create. I will explain the code below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> cookie <span class="hljs-keyword">from</span> <span class="hljs-string">'cookie'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">if</span> (req.method === <span class="hljs-string">'POST'</span>) {
    <span class="hljs-comment">// DESTROY COOKIE</span>
    res.setHeader(
      <span class="hljs-string">'Set-Cookie'</span>,
      cookie.serialize(<span class="hljs-string">'token'</span>, <span class="hljs-string">''</span>, {
        <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">secure</span>: process.env.NODE_ENV !== <span class="hljs-string">'development'</span>,
        <span class="hljs-attr">expires</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-number">0</span>),
        <span class="hljs-attr">sameSite</span>: <span class="hljs-string">'strict'</span>,
        <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>
      })
    )

    res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Success"</span>})

  } <span class="hljs-keyword">else</span> {
    res.setHeader(<span class="hljs-string">'Allow'</span>, [<span class="hljs-string">'POST'</span>])
    res.status(<span class="hljs-number">405</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">`Method <span class="hljs-subst">${req.method}</span> not allowed`</span> })
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> logout
</code></pre>
<p>All we are doing here is just to destroy the cookie. Now if you look at the <code>cookie.serialize('token', '',)</code> you will see that the token is now set to an empty string.
Next we replace the <code>maxAge</code> with <code>expires</code> and we want to set it to something that's pass and we did that by passing a new data and pass in zero. And that's it this should destroy the cookie.
Now from our logout function in out <code>AuthContext</code> we just want to call that <code>api/logout.js</code> Now add these code inside of the <code>logout</code> function inside of the <code>AuthContext</code></p>
<pre><code class="lang-javascript">
  <span class="hljs-keyword">const</span> logout = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${NEXT_URL}</span>/api/logout`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
    })

    <span class="hljs-keyword">if</span> (res.ok) {
      setUser(<span class="hljs-literal">null</span>)
      router.push(<span class="hljs-string">'/login'</span>)
    }
  }
</code></pre>
<p>What we are doing here is simply hitting that <code>api/logout</code> route and we then <code>setUser(null)</code> to <code>null</code>, this will remove our cookie, and redirect the user to the login page. Now let's go to our <code>Navbar</code> components and bring in the <code>logout</code> method from <code>AuthContext</code>, So now update your <code>navbar</code> component with this code below</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> { logout, user } = useContext(AuthContext)

{user ? <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/dashboard"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> logout()}&gt;Logout<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/&gt;</span></span> : <span class="hljs-literal">null</span>}
</code></pre>
<p>Now once you click on logout everything should be working very fine, the cookie will be destroy.
Now the next thing is the register page, basically this will do the same thing as login except it will create the user and then it will send back the token basically do the same thing the login response does.</p>
<h3 id="heading-register-user">Register User</h3>
<p>Now let's go to our <code>api</code> folder and create our <code>register.js</code> file.
Now go ahead and copy these code and paste inside of your <code>register.js</code> file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { API_URL } <span class="hljs-keyword">from</span> <span class="hljs-string">'../../config/index'</span>
<span class="hljs-keyword">import</span> cookie <span class="hljs-keyword">from</span> <span class="hljs-string">'cookie'</span>

<span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">if</span> (req.method === <span class="hljs-string">'POST'</span>) {

    <span class="hljs-keyword">const</span> {fullname, email, password} = req.body

    <span class="hljs-keyword">const</span> apiRes = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${API_URL}</span>/your register endpoint`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        fullname,
        email,
        password
      }),
    })

    <span class="hljs-keyword">const</span> resData = <span class="hljs-keyword">await</span> apiRes.json()

    <span class="hljs-comment">// console.log(resData.data.token)</span>

    <span class="hljs-keyword">if</span> (apiRes.ok) {
      <span class="hljs-comment">// Set Cookie</span>
      res.setHeader(
        <span class="hljs-string">'Set-Cookie'</span>,
        cookie.serialize(<span class="hljs-string">'token'</span>, <span class="hljs-built_in">String</span>(resData.data.token), {
          <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
          <span class="hljs-attr">secure</span>: process.env.NODE_ENV !== <span class="hljs-string">'development'</span>,
          <span class="hljs-attr">maxAge</span>: <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">7</span>, <span class="hljs-comment">// 1 week</span>
          <span class="hljs-attr">sameSite</span>: <span class="hljs-string">'strict'</span>,
          <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>
        })
      )

      res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">user</span>: resData.data })
    } <span class="hljs-keyword">else</span> {
      res.status(<span class="hljs-number">500</span>).json({<span class="hljs-attr">message</span>: resData.message})
    }
  } <span class="hljs-keyword">else</span> {
    res.setHeader(<span class="hljs-string">'Allow'</span>, [<span class="hljs-string">'POST'</span>])
    res.status(<span class="hljs-number">405</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">`Method <span class="hljs-subst">${req.method}</span> not allowed`</span> })
  }
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> register
</code></pre>
<p>Now if you take a close look you will see that we are doing the same thing as the login route, the little difference here is that we are accepting an extra field which is <code>fullname</code>. So next let's dive right into the <code>AuthContext</code> and handle the <code>register</code> route we have just created. You can copy the code below and paste it into the <code>register async function</code> we created.</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// Resister user</span>
  <span class="hljs-comment">// ====================================</span>
  <span class="hljs-keyword">const</span> signup = <span class="hljs-keyword">async</span> ({ fullname, email, password }) =&gt; {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`<span class="hljs-subst">${NEXT_URL}</span>/api/register`</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ fullname, email, password }),
    })

    <span class="hljs-keyword">const</span> resData = <span class="hljs-keyword">await</span> res.json()

    <span class="hljs-keyword">if</span> (res.ok) {
      setUser(resData.user)
      router.push(<span class="hljs-string">'/dashboard'</span>)
    } <span class="hljs-keyword">else</span> {
      setIsError(resData.message)
      setIsError(<span class="hljs-literal">null</span>)
    }
  }
</code></pre>
<p>Now we are hitting the <code>api/register.js</code> route that we just created, we are sending along the user object which is the <code>fullname, email, password</code> then we check to see if the response is ok, if is okay then we set the user and push/redirect to the dashboard and if there's an error we set that in the state.
Now let's go inside the <code>register</code> and update our <code>handleRegisterSubmit</code> with these code</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">const</span> handleRegisterSubmit = <span class="hljs-keyword">async</span> ({ fullname, email, password }) =&gt; {
    register({ fullname, email, password })
  }
</code></pre>
<p>Now you can go ahead and test your app, everything should be working very fine now.</p>
<h4 id="heading-conclusion">Conclusion</h4>
<p>So having these API routes and being able to set an HTTP-only cookie is another big benefit of using Next.Js because is not something you can do with just React. 
Where to store JSON Web Tokens has always been kind of an issue with front-end development. So this does give us one solution.</p>
<p>Hello, I hope you liked the article. I am Caleb, a software developer. Let's connect at <a target="_blank" href="https://twitter.com/calebbenjin">Twitter</a>  </p>
]]></content:encoded></item></channel></rss>