<?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: NathLowe</title>
    <description>The latest articles on DEV Community by NathLowe (@nathlowe).</description>
    <link>https://dev.to/nathlowe</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%2F1083345%2F69fa9aae-f14d-4f45-93f4-537dd6a35060.jpeg</url>
      <title>DEV Community: NathLowe</title>
      <link>https://dev.to/nathlowe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nathlowe"/>
    <language>en</language>
    <item>
      <title>My Code Chronicles #3: Partial Pre-Rendering in Next.js - A Cart Page Example</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Thu, 23 Jan 2025 08:45:34 +0000</pubDate>
      <link>https://dev.to/nathlowe/my-code-chronicles-3-partial-pre-rendering-in-nextjs-a-cart-page-example-4l07</link>
      <guid>https://dev.to/nathlowe/my-code-chronicles-3-partial-pre-rendering-in-nextjs-a-cart-page-example-4l07</guid>
      <description>&lt;p&gt;In modern web development, ensuring fast load times and a seamless user experience is crucial. Partial pre-rendering, a powerful feature in Next.js, bridges the gap between Static Site Generation (SSG) and Server-Side Rendering (SSR) by selectively prerendering parts of a page while leaving others dynamic. In this article, we’ll dive into partial pre-rendering, using a Cart Page as an example. &lt;em&gt;(This is kind of a complex example because it implicates 2 dynamic sections. If you guys want a simpler one, let me know.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Partial Pre-Rendering?
&lt;/h2&gt;

&lt;p&gt;Partial pre-rendering allows us to optimize performance by prerendering static sections of a page while dynamically fetching and rendering frequently changing or user-specific data. It uses features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static pre-rendering&lt;/strong&gt; for predictable content (headers, footers, page layout).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic rendering&lt;/strong&gt; for data fetched at runtime (e.g., user carts, recommendations).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suspense boundaries&lt;/strong&gt; to handle asynchronous loading elegantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Use Partial Pre-Rendering?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Improved Performance:&lt;/strong&gt; By prerendering static parts, users interact with pages faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better SEO:&lt;/strong&gt; Static content is ready for search engine crawlers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced User Experience:&lt;/strong&gt; Dynamic components load seamlessly within placeholders or fallbacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Cart Page Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;On our Cart Page, the static and dynamic parts are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Static: Page structure, layout components, and Fallbacks (Cart Content &amp;amp; Similar Products Placeholders).&lt;/li&gt;
&lt;li&gt;Dynamic:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cart Content:&lt;/strong&gt; Fetched directly in the server component before rendering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Similar Products Section:&lt;/strong&gt; Fetched dynamically after the page has loaded using a suspense boundary.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Code Walkthrough
&lt;/h3&gt;

&lt;p&gt;Below is the code for the Cart Page using partial pre-rendering.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Static Layout and Dynamic Cart Content
&lt;/h4&gt;

&lt;p&gt;The main structure of the page is prerendered, while cart data is fetched on the server using an asynchronous function in a server component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// imports...

export default async function CartPage() {
  // Fetch cart data on the server
  const { cart, areProductsInCart, productsIds } = await initiateCart();

  return (
    &amp;lt;main&amp;gt;
      &amp;lt;h1 className="sr-only"&amp;gt;Cart Page&amp;lt;/h1&amp;gt;
      &amp;lt;Section className="max-w-[1400px]"&amp;gt;
        &amp;lt;CheckoutLayoutWrapper&amp;gt;
          &amp;lt;CheckoutLayoutContent&amp;gt;
            &amp;lt;SectionHeader
              tag={areProductsInCart ? `${cart.itemsCount} item(s)` : undefined}
              title="Cart Page"
              isCheckoutPage
            /&amp;gt;
            &amp;lt;Card className="rounded-special w-full bg-primary-light shadow"&amp;gt;
              &amp;lt;CardContent&amp;gt;
                {!areProductsInCart ? (
                  &amp;lt;EmptySection
                    title="Your cart is empty! Please add some products."
                  /&amp;gt;
                ) : (
                  &amp;lt;&amp;gt;
                    {/* Desktop Cart Content */}
                    &amp;lt;CartContentDesktop cartProducts={cart.cartProducts} /&amp;gt;

                    {/* Mobile Cart Content */}
                    &amp;lt;CartContentMobile cartProducts={cart.cartProducts} /&amp;gt;
                  &amp;lt;/&amp;gt;
                )}
              &amp;lt;/CardContent&amp;gt;
            &amp;lt;/Card&amp;gt;
          &amp;lt;/CheckoutLayoutContent&amp;gt;

          {/* Sidebar for Cart Total and Coupon Code */}
          {areProductsInCart &amp;amp;&amp;amp; (
            &amp;lt;CheckoutLayoutSidebar&amp;gt;
              {/* Coupon Code */}
              &amp;lt;CartCouponCode /&amp;gt;

              {/* Cart Total */}
              &amp;lt;CartTotal cartData={cart?.allItemsWithData} /&amp;gt;
            &amp;lt;/CheckoutLayoutSidebar&amp;gt;
          )}
        &amp;lt;/CheckoutLayoutWrapper&amp;gt;

        {/* Related Products Section */}
        &amp;lt;CartSimilarProducts productIdsToExclude={productsIds ?? []} /&amp;gt;
      &amp;lt;/Section&amp;gt;
    &amp;lt;/main&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Loading State
&lt;/h4&gt;

&lt;p&gt;When cart data is being fetched, a loading.tsx component is displayed as a fallback. This is the default feature from NextJs App folder. This Loading component displays the placeholders of both the Cart Content And The Similar Products.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default async function CartPage() {
  return (
    &amp;lt;main&amp;gt;
      &amp;lt;h1 className="sr-only"&amp;gt;Cart Page&amp;lt;/h1&amp;gt;
      &amp;lt;Section className="max-w-[1400px]"&amp;gt;
        &amp;lt;CheckoutLayoutWrapper&amp;gt;
          &amp;lt;CheckoutLayoutContent&amp;gt;
            &amp;lt;SectionHeaderLoader isCheckoutPage /&amp;gt;
            &amp;lt;Card className="rounded-special w-full bg-primary-light shadow"&amp;gt;
              &amp;lt;CardContent&amp;gt;
                {/* Desktop */}
                &amp;lt;CartContentDesktopLoader /&amp;gt;

                {/* Mobile */}
                &amp;lt;CartContentMobileLoader /&amp;gt;
              &amp;lt;/CardContent&amp;gt;
            &amp;lt;/Card&amp;gt;
          &amp;lt;/CheckoutLayoutContent&amp;gt;

          {/* Sidebar */}
          {/* Add Sidebar loader later maybe */}
        &amp;lt;/CheckoutLayoutWrapper&amp;gt;

        {/* Related Products */}
        &amp;lt;CartSimilarProductsLoader /&amp;gt;
      &amp;lt;/Section&amp;gt;
    &amp;lt;/main&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Similar Products with Suspense
&lt;/h4&gt;

&lt;p&gt;The Similar Products component fetches data dynamically and is wrapped in a suspense boundary. While data is being fetched, a placeholder (fallback) is shown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function CartSimilarProducts({ productIdsToExclude }) {
  return (
    &amp;lt;Suspense fallback={&amp;lt;CartSimilarProductsLoader /&amp;gt;}&amp;gt;
      {/* Actual similar products component */}
      &amp;lt;SimilarProducts productIdsToExclude={productIdsToExclude} /&amp;gt;
    &amp;lt;/Suspense&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Flow Recap
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: Cart Content data is being fetched. On the website, the fallback (placeholder for both the cart content and the similar products) are pre-rendered.&lt;/li&gt;
&lt;li&gt;Step 2a: Cart Content data is fully fetched. On the website, all the pre-rendered content is replaced by the actual content.&lt;/li&gt;
&lt;li&gt;Step 2b: Similar Products Content is being fetched. The content is the same as above. However, in the actual content, there is the Cart content and a pre-rendered placeholder for the cart similar products. Though it is the same content and display as in the previous fallback it is not the exact same component.&lt;/li&gt;
&lt;li&gt;Step 3: Similar Products Content is fully fetched. On the website, we can now see both the Cart content and the Similar Products content.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Partial pre-rendering is a game-changer for building performant and dynamic applications. By leveraging Next.js's capabilities, we efficiently balance static and dynamic content on our Cart Page, enhancing both speed and user experience. &lt;strong&gt;If we are to be completely honest and literal, this is not Partial Pre-rendering, it is some kind of Nested Pre-Rendering. However, it does the trick if you are looking for Partial Pre-rendering.&lt;/strong&gt; The Next.js team is actually working on developing a "real" Partial Pre-rendering feature, it is actually on "unstable" but might be operational in the next version.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>partialprerendering</category>
    </item>
    <item>
      <title>My Code Chronicles #2: Creating a Dynamic Product Card Component in Next.js using Framer Motion</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Sun, 19 Jan 2025 00:47:27 +0000</pubDate>
      <link>https://dev.to/nathlowe/my-code-chronicles-2-creating-a-dynamic-product-card-component-in-nextjs-using-framer-motion-3agh</link>
      <guid>https://dev.to/nathlowe/my-code-chronicles-2-creating-a-dynamic-product-card-component-in-nextjs-using-framer-motion-3agh</guid>
      <description>&lt;p&gt;Hover effects are more than just eye candy—they are essential for creating an engaging user experience on modern websites. When implemented thoughtfully, hover effects can provide subtle visual feedback, improve usability, and guide user interaction intuitively.&lt;/p&gt;

&lt;p&gt;For e-commerce websites, like the one I was building for &lt;a href="//glamourandgourmandise.com"&gt;Glamour &amp;amp; Gourmandise&lt;/a&gt;, the product card is a critical component. It needs to be visually appealing, informative, and highly interactive. To achieve this, I implemented a sophisticated hover effect that reveals additional product details in a sleek and seamless way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

import { motion } from "framer-motion" 
// Imports...


export default function ProductCard(){

  // State
  const [isHovered, setIsHovered] = useState(false);

  return (
    &amp;lt;article
      tabIndex={0}
      className={cn(
        "rounded-special group/product relative flex h-fit cursor-pointer flex-col overflow-hidden",
        "aspect-[4/5] border-2 border-dashed border-primary/20 sm:aspect-square md:aspect-[4/5]",
      )}
      onMouseEnter={() =&amp;gt; setIsHovered(true)}
      onMouseLeave={() =&amp;gt; setIsHovered(false)}
    &amp;gt;
      {/* Product Image */}
      &amp;lt;Image
       src={image}
       alt={alt}
       className={cn(
         "h-auto w-full flex-none object-cover",
         "h-[58%] flex-none sm:aspect-auto",
       )}
      /&amp;gt;

      {/* Product Details */}
      &amp;lt;div
        className={cn(
          "group relative h-[42%] w-full grow",
          isHovered ? "is-hovered" : "",
        )}
      &amp;gt;
        &amp;lt;motion.div
          layout
          transition={{
            layout: { duration: 0.1 },
            // default: { ease: "linear" },
          }}
          className={cn(
            "rounded-special absolute bottom-0 left-0 flex min-h-[105%] w-full flex-col justify-between space-y-2 bg-white p-2 group-[.is-hovered]:h-auto sm:space-y-4 sm:p-3 lg:p-4",
            "",
          )}
        &amp;gt;
          &amp;lt;div className="flex-none"&amp;gt;
            &amp;lt;h3 className="line-clamp-2 font-title font-semibold !leading-[1.1] min-[480px]:text-lg min-[545px]:text-2xl sm:mb-1"&amp;gt;
              {product.title}
            &amp;lt;/h3&amp;gt;
            &amp;lt;div className="mb-1 hidden h-0 items-center space-x-1 overflow-hidden group-[.is-hovered]:flex group-[.is-hovered]:h-auto sm:mb-3"&amp;gt;
              {product.tags.map(
                ({ tag }, i) =&amp;gt;
                  i &amp;lt; 2 &amp;amp;&amp;amp; (
                    &amp;lt;Badge variant="product-tag" key={i} className=""&amp;gt;
                      {tag}
                    &amp;lt;/Badge&amp;gt;
                  ),
              )}
            &amp;lt;/div&amp;gt;
            &amp;lt;p className="line-clamp-3 hidden text-xs leading-[1.1] text-muted-foreground group-[.is-hovered]:line-clamp-3 md:text-sm"&amp;gt;
              {product.description}
            &amp;lt;/p&amp;gt;
            {product.link &amp;amp;&amp;amp; (
              &amp;lt;Link
                onClick={(e) =&amp;gt; e.stopPropagation()}
                replace
                href={product.link}
                className="block w-fit text-xs font-semibold text-primary transition hover:text-secondary group-[.is-hovered]:block sm:hidden"
              &amp;gt;
                More info
              &amp;lt;/Link&amp;gt;
            )}
          &amp;lt;/div&amp;gt;

          &amp;lt;div className="flex flex-wrap items-center justify-between gap-2"&amp;gt;
            &amp;lt;div className=""&amp;gt;
              &amp;lt;p className="font-title text-sm font-semibold leading-none min-[400px]:text-xl"&amp;gt;
                {product.formattedPrice.priceWithCurrency}
              &amp;lt;/p&amp;gt;
              &amp;lt;span className="hidden text-right text-[0.6rem] leading-none text-secondary min-[545px]:block sm:text-xs"&amp;gt;
                {product.formattedPrice.priceUnit}
              &amp;lt;/span&amp;gt;
            &amp;lt;/div&amp;gt;

            {/* Add To Cart Button */}
            &amp;lt;Button size="sm" disabled={true}&amp;gt;
                  &amp;lt;span className="block size-4 animate-spin rounded-full border border-current border-t-transparent" /&amp;gt;
                &amp;lt;/Button&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/motion.div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/article&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Wrapper
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;article&lt;/code&gt; element is the foundation of this hover effect. It is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintaining the aspect ratio (responsively adjusted based on screen size).&lt;/li&gt;
&lt;li&gt;Housing all child components, including the image and product details.&lt;/li&gt;
&lt;li&gt;Triggering hover state changes.&lt;/li&gt;
&lt;li&gt;Aspect Ratio: Ensures consistent sizing of the card across different devices.&lt;/li&gt;
&lt;li&gt;Hover State: Sets &lt;code&gt;isHovered&lt;/code&gt; to true or false to control the animation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Product Details Section
&lt;/h3&gt;

&lt;p&gt;The product details are housed in an absolutely positioned &lt;code&gt;div&lt;/code&gt; at the bottom of the wrapper. This positioning ensures that the expanding animation occurs within the wrapper, avoiding disruptions to the page layout.&lt;br&gt;
Framer Motion’s &lt;code&gt;layout={true}&lt;/code&gt; is the key to this hover effect. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Animates Height Changes&lt;/strong&gt;: When the product details expand, layout={true} calculates the difference in height and interpolates the transition smoothly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direction Control&lt;/strong&gt;: Because the details div is positioned absolutely at the bottom, the expansion happens upward into the card instead of downward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-Friendly Transitions&lt;/strong&gt;: Without &lt;code&gt;layout={true}&lt;/code&gt;, the height change would feel abrupt and jarring.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This hover effect showcases how to elevate user experience with smooth animations and thoughtful design. While the actual website for Glamour &amp;amp; Gourmandise opted for a simpler zoom-in effect on images (as per the owner’s preference), this implementation demonstrates the versatility and creative possibilities with Framer Motion and Next.js.&lt;br&gt;
If you’re interested in learning more about layout animations or have tips to optimize this implementation further, let me know!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>motion</category>
      <category>ecommerce</category>
      <category>typescript</category>
    </item>
    <item>
      <title>My Code Chronicles #1: Optimizing Images in Next.js with a Custom Component</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Fri, 17 Jan 2025 19:56:47 +0000</pubDate>
      <link>https://dev.to/nathlowe/my-code-chronicles-1-optimizing-images-in-nextjs-with-a-custom-component-3973</link>
      <guid>https://dev.to/nathlowe/my-code-chronicles-1-optimizing-images-in-nextjs-with-a-custom-component-3973</guid>
      <description>&lt;p&gt;First Contentful Paint (FCP) is a critical performance metric that measures the time it takes for the first piece of content to appear on the screen after a user navigates to a page. A fast FCP is essential for providing a good user experience, as it gives users visual feedback that the page is loading.&lt;/p&gt;

&lt;p&gt;However, using large, high-quality images can significantly delay the FCP, which impacts perceived performance. At the same time, high-quality images are vital for creating a visually appealing and professional website. Balancing fast load times and maintaining good image quality is often challenging.&lt;/p&gt;

&lt;p&gt;To address this, I created a custom Next.js client component for images. This component initially renders a placeholder block when the page is built. After hydration, it uses JavaScript to load the image and only displays it once it has been fully loaded. Let’s dive into how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initial Placeholder Rendering&lt;/strong&gt;: During the page’s build and hydration phases, the component renders a placeholder (e.g., a skeleton or loader) instead of the actual image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JavaScript Image Preloading&lt;/strong&gt;: After hydration, the browser preloads the image using JavaScript. The image is only displayed once it has been fully loaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Responsive Sizing&lt;/strong&gt;: The component supports responsive sizing via the &lt;code&gt;setSizes&lt;/code&gt;prop, which allows developers to define image sizes for different screen breakpoints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loader Feedback&lt;/strong&gt;: While the image is loading, a custom loader (e.g., a spinner or skeleton) is displayed to provide a better user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverages Next.js Optimization&lt;/strong&gt;: The component integrates seamlessly with Next.js’s &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt; for optimized image handling.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code Overview
&lt;/h2&gt;

&lt;p&gt;Here’s the complete implementation of the &lt;code&gt;MyImage&lt;/code&gt;component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

import React, { ComponentProps, useEffect, useState } from "react";
import NextImage, { StaticImageData } from "next/image";

import ImageLoader from "./loader";
import { cn } from "@/lib/utils";

type NextImageProps = ComponentProps&amp;lt;typeof NextImage&amp;gt;;
type ImageProps = NextImageProps &amp;amp; {
  showLoaderIcon?: boolean;
  setSizes?: {
    default: number;
    sm?: number;
    md?: number;
    lg?: number;
    xl?: number;
  };
  src: string | StaticImageData;
};

const generateSize = (sizes: ImageProps["setSizes"]): string | undefined =&amp;gt; {
  let size: undefined | string = undefined;
  if (sizes) {
    size = `${sizes.default}vw`;
    if (sizes.sm) size = `(min-width: 640px) ${sizes.sm}vw, ${size}`;
    if (sizes.md) size = `(min-width: 768px) ${sizes.md}vw, ${size}`;
    if (sizes.lg) size = `(min-width: 1024px) ${sizes.lg}vw, ${size}`;
    if (sizes.xl) size = `(min-width: 1280px) ${sizes.xl}vw, ${size}`;
  }

  return size;
};

export default function MyImage(props: ImageProps) {
  const { className, src } = props;

  const [isLoading, setIsLoading] = useState(true);

  useEffect(() =&amp;gt; {
    if (document) {
      const image = new Image();
      image.onerror = () =&amp;gt; {
        // Handle error if needed
      };
      image.src = typeof src === "string" ? src : src.src;
      image.onload = () =&amp;gt; {
        setIsLoading(false);
      };
    }
  }, []);

  const newProps = {
    ...props,
    className: cn(className, "relative animation-fade-in"),
    fill:
      props.width !== undefined || props.height !== undefined ? false : true,
    sizes:
      props.width !== undefined || props.height !== undefined
        ? undefined
        : props.sizes ?? generateSize(props.setSizes),
  };

  if (isLoading)
    return (
      &amp;lt;ImageLoader
        showIcon={props.showLoaderIcon}
        className={`${className} relative overflow-hidden`}
      /&amp;gt;
    );

  if (newProps.showLoaderIcon !== undefined) delete newProps.showLoaderIcon;
  if (newProps.setSizes !== undefined) delete newProps.setSizes;
  if (newProps.fill)
    return (
      &amp;lt;div className={`${className} relative overflow-hidden`}&amp;gt;
        &amp;lt;NextImage
          {...newProps}
          src={typeof src === "string" ? src : src.src}
          loading="lazy"
        /&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  return (
    &amp;lt;NextImage
      {...newProps}
      src={typeof src === "string" ? src : src.src}
      loading="lazy"
    /&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initial Placeholder Rendering&lt;/strong&gt;: When the component is mounted, a placeholder is shown using the ImageLoader component.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { FaImage } from "react-icons/fa";

// Types
interface ImageLoaderProps {
  className?: string;
  showIcon?: boolean;
}

export default function ImageLoader({ className, showIcon }: ImageLoaderProps) {
  className = className || "w-full h-full";
  showIcon = showIcon ?? true;
  return (
    &amp;lt;div
      className={`${className} flex flex-none animate-pulse items-center justify-center bg-primary/30`}
    &amp;gt;
      {showIcon &amp;amp;&amp;amp; (
        &amp;lt;FaImage className="aspect-square h-auto w-6 max-w-[40%] text-primary/80 md:w-10 lg:w-14" /&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Preloading and State Management&lt;/strong&gt;: The &lt;code&gt;useEffect&lt;/code&gt;hook uses a native Image object to preload the image in the background. The &lt;code&gt;isLoading&lt;/code&gt; state determines whether the placeholder or the actual image is displayed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Responsive Sizes&lt;/strong&gt;: The generateSize function dynamically calculates the sizes attribute based on the screen’s viewport.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Final Image Rendering&lt;/strong&gt;: Once preloading is complete, the image is displayed using Next.js’s &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt;, with all the necessary props and optimizations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This custom image component provides a robust solution for optimizing image performance in Next.js. By displaying a placeholder initially and loading images only after hydration, it ensures a faster FCP without sacrificing quality.&lt;/p&gt;

&lt;p&gt;However, there’s a small challenge I’m still working on: when the image appears after being loaded in the background, there’s a short delay. I suspect this delay is related to the rendering process of the image. If anyone has insights or solutions to address this, I would greatly appreciate your input.&lt;/p&gt;

&lt;p&gt;Stay tuned for more posts in My Code Chronicles, where I share technical tips, challenges, and solutions from my development journey!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>pageopt</category>
    </item>
    <item>
      <title>Next.js 13: Introduction to Client-Side Rendering and Client Components</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Tue, 03 Oct 2023 03:08:48 +0000</pubDate>
      <link>https://dev.to/nathlowe/nextjs-13-introduction-to-client-side-rendering-and-client-components-5hd9</link>
      <guid>https://dev.to/nathlowe/nextjs-13-introduction-to-client-side-rendering-and-client-components-5hd9</guid>
      <description>&lt;p&gt;Client-side englobes the processes that happen on the user’s device, usually in the user’s web browser. These processes are done after the website or web application has been sent to the user’s device, and they can involve tasks such as showing and rendering a web page, dealing with user interactions, or running JavaScript code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Content
&lt;/h2&gt;

&lt;p&gt;I. How to use Client-Side in NextJS 13?&lt;br&gt;
II. How are Client Components Rendered?&lt;br&gt;
III. Benefits of Client Component&lt;br&gt;
IV. Tips when working with Client Components&lt;br&gt;
    1. Moving Client Components Down the Tree&lt;br&gt;
    2. Avoid Importing Server Components into Client Components&lt;br&gt;
V. Recap&lt;/p&gt;
&lt;h2&gt;
  
  
  How to use Client-Side in NextJS 13?
&lt;/h2&gt;

&lt;p&gt;To enable client-side rendering (&lt;strong&gt;CSR&lt;/strong&gt;) in NextJS 13, you need to use Client Components. You can create Client Components by adding the &lt;code&gt;"use client"&lt;/code&gt; directive at the beginning of a file before your imports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“use client” //at the top of the page

// YOUR CODE HERE

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

&lt;/div&gt;



&lt;p&gt;When you use &lt;code&gt;"use client"&lt;/code&gt; in a file, all the other modules that you import into it, including child components, are part of the client bundle - and will be rendered by React on the client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good To Know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You can define multiple &lt;code&gt;"use client"&lt;/code&gt; entry points in your React Component tree. This allows you to split your application into multiple client bundles (or branches). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Components without the &lt;code&gt;“use client”&lt;/code&gt; directive being used in a Client Component (with &lt;code&gt;“use client”&lt;/code&gt;) are still considered to be Client Components.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How are Client Components Rendered?
&lt;/h2&gt;

&lt;p&gt;Client Components are rendered in different ways in Next.js depending on whether the request is for a &lt;strong&gt;full page load&lt;/strong&gt; (when you first visit your application or when you reload the page using the browser refresh) or for a &lt;strong&gt;subsequent navigation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;full page load&lt;/strong&gt;, to make the initial page load faster, Next.js will use React’s APIs to create a static HTML preview on the server for both Client and Server Components. This means, when the user first visits your application, they will see the content of the page right away, without having to wait for the client to download, parse, and run the Client Component JavaScript bundle. Then, on the client (navigator), the JavaScript instructions are used to &lt;strong&gt;hydrate&lt;/strong&gt; Client Components and make their UI interactive.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;subsequent navigations&lt;/strong&gt;, Client Components are rendered entirely on the client, without the server-rendered HTML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Client Component
&lt;/h2&gt;

&lt;p&gt;Actually, for Client Components, we should talk more about use cases than benefits, as these “&lt;em&gt;benefits&lt;/em&gt;” are already what we get with a simple React Application. We have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interactivity&lt;/strong&gt;: Client Components can use state, effects, and event listeners.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser APIs&lt;/strong&gt;: Client Components have access to browser APIs, like geolocation or localStorage, allowing you to build UI for specific use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips when working with Client Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Moving Client Components Down the Tree
&lt;/h3&gt;

&lt;p&gt;To reduce the Client JavaScript bundle size, it is recommended to move Client Components down your component tree. I struggled to get it at first, but with an example it is easy to understand.&lt;/p&gt;

&lt;p&gt;For example, you may have a &lt;code&gt;&amp;lt;Navbar&amp;gt;&lt;/code&gt; Component that has static elements (e.g. logo, links, etc) and an interactive &lt;strong&gt;search bar&lt;/strong&gt; that uses state.&lt;/p&gt;

&lt;p&gt;Instead of making the whole &lt;code&gt;&amp;lt;Navbar&amp;gt;&lt;/code&gt; a Client Component, move the interactive logic to a Client Component (e.g. &lt;code&gt;&amp;lt;SearchBar/&amp;gt;&lt;/code&gt;) and keep your layout as a Server Component. This means you don't have to send all the component Javascript of the &lt;code&gt;&amp;lt;Navbar&amp;gt;&lt;/code&gt; to the client, resulting in a faster page loading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SearchBar is a Client Component
import SearchBar from './searchbar'
// Logo is a Server Component
import Logo from './logo'

// Navbar is a Server Component by default
export default function Navbar({ children }: { children: React.ReactNode }) {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;nav&amp;gt;
        &amp;lt;Logo /&amp;gt;
        &amp;lt;SearchBar /&amp;gt;
      &amp;lt;/nav&amp;gt;
      &amp;lt;main&amp;gt;
        {children}
      &amp;lt;/main&amp;gt;
    &amp;lt;/&amp;gt;
  )
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Avoid Importing Server Components into Client Components
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;You cannot use Server Components in Client Components&lt;/strong&gt;. However, you can import components that do not have the &lt;code&gt;“use client”&lt;/code&gt; directive into a Client Component, but it is not recommended. If that component does not use server components features (headers, async/await etc), it will work fine. But if you do not specify that it is a Client Component from the start, you could easily make the mistake of using Server Components features and therefore cause some errors.&lt;/p&gt;

&lt;p&gt;If you really want to use a Server Component in a Client Component, the best way to achieve it is to wrap the Server Component with the client component (meaning pass the Server Component as a child of the Client one)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;&amp;lt;ServerComponentMain/&amp;gt;&lt;/code&gt; Server Component&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import ServerComponent from …
import ClientComponent from …

export default function ServerComponentMain() {
    return (
        &amp;lt;ClientComponent&amp;gt;
            &amp;lt;ServerComponent/&amp;gt;
        &amp;lt;/ClientComponent&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;code&gt;&amp;lt;ClientComponent&amp;gt;&lt;/code&gt; Client Component&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“use client”

// import your modules here

export default function ClientComponent ({ children }: { children: React.ReactNode }){
    /* Client code, useState, useEffect… */
    return (
        &amp;lt;ClientComponent&amp;gt;
            {children}
        &amp;lt;/ClientComponent&amp;gt;
    )
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;Client-Side Rendering is the process of rendering the web page on the user’s device using JavaScript. &lt;br&gt;
Client components are a new feature in Next.js 13 that allows you to create components that sometimes run on the server but mostly on the client having access to browser APIs and hooks.&lt;br&gt;
Some tips on how to use client components effectively are moving the client components down the tree, avoiding importing server components into client components.&lt;/p&gt;

&lt;p&gt;In the next article, we will explore Server Side and Server Components in Next.js 13. Stay tuned!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Next.js 13: A Comprehensive Guide</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Sun, 01 Oct 2023 04:24:29 +0000</pubDate>
      <link>https://dev.to/nathlowe/nextjs-13-a-comprehensive-guide-4cja</link>
      <guid>https://dev.to/nathlowe/nextjs-13-a-comprehensive-guide-4cja</guid>
      <description>&lt;p&gt;Hello, I’m a frontend web developer specializing in React and &lt;strong&gt;Next.js&lt;/strong&gt;. I’ve decided to share my knowledge and experience with the community through a series of articles focusing on coding tips and error decryption for React and Next.js. The purpose of this series is to help other developers navigate the complexities of these technologies, particularly the latest version of Next.js - Next.js 13.&lt;/p&gt;

&lt;p&gt;In this first article, we’ll be diving into Next.js 13, exploring its differences with other tools, its advantages and disadvantages, and whether it’s a good fit for your projects. As a developer who has spent considerable time working with Next.js 13, I can attest to its greatness. It’s quite different from the previous versions and can be challenging to grasp initially, but the more you code with it, the better it gets. Yes, it has its fair share of bugs, but the Vercel team is consistently working on improvements. And I’m here to show you how to work around these bugs and errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Next.js 13?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Next.js 13.4 is a JavaScript framework built on top of React. It introduces several new features that make it dynamic without limits. Some of these features include:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;App Directory&lt;/strong&gt;: This makes routing and layouts easier and faster.&lt;br&gt;
• &lt;strong&gt;React Server Components&lt;/strong&gt;: This makes server-first the default for dynamic applications.&lt;br&gt;
• &lt;strong&gt;Streaming&lt;/strong&gt;: This displays instant loading states and streams in units of UI as they are rendered.&lt;br&gt;
• &lt;strong&gt;Turbopack (alpha)&lt;/strong&gt;: This is a Rust-based Webpack replacement that is up to 700x faster. For now, this is just to be used for development and is totally worth it. Give it a try! (you just need to run &lt;code&gt;npm run dev --turbo&lt;/code&gt;)&lt;br&gt;
• &lt;strong&gt;New next/image&lt;/strong&gt;: This makes images load faster with native browser lazy loading.&lt;br&gt;
• &lt;strong&gt;New @next/font&lt;/strong&gt;: This allows for automatic self-hosted fonts with zero layout shift.&lt;br&gt;
• &lt;strong&gt;Improved next/link&lt;/strong&gt;: This simplifies API with automatic &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Comparison with Other Tools&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Next.js 13 stands out from other tools due to its wide range of features and flexibility. It’s perfect for creating both static and dynamic web pages, with the added benefit of merging the two using &lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;When compared to Next.js 12, it introduces several new concepts such as pre-rendering (SSG vs SSR), server and client components, file differences, page &amp;amp; API routing, data fetching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gatsby&lt;/strong&gt; is a free and open-source framework that excels in building static websites. However, it may not be as flexible as Next.js when it comes to rendering methods.&lt;/p&gt;

&lt;p&gt;As for &lt;strong&gt;Remix&lt;/strong&gt;, a newer framework that aims to bring back the simplicity of Web 1.0. It supports SSR with Edge deployment and couples routing with data loading. However, it may not be as mature as Next.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Pros and Cons of Next.js 13&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Disregarding SEO, SSR, and other features that were already introduced in earlier versions, the 13th version of Next.js presents three primary advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Better user experience&lt;/strong&gt;: It provides a truly outstanding and customized user experience.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Above-average performance&lt;/strong&gt;: It helps in creating performant web applications and superfast static websites.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Rapid feature development&lt;/strong&gt;: It supports rapid feature development which is beneficial for both large companies like Netflix and Uber as well as smaller companies that are just starting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the other hand, Next.js 13 also has some disadvantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Bugs&lt;/strong&gt;: As with any new technology, there are bugs that need to be addressed. However, the Vercel team is consistently working on improvements.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Learning curve&lt;/strong&gt;: Due to its many new features and changes from previous versions, there can be a steep learning curve for developers new to Next.js or upgrading from an older version.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Recap: Is Next.js 13 a Good Fit?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In my opinion, despite some initial challenges and bugs, Next.js 13 is a great tool for web development. The more you work with it, the better it gets. Its wide range of features provides flexibility for developers while its performance enhancements offer a better user experience.&lt;/p&gt;

&lt;p&gt;However, whether it’s a good fit for you would depend on your specific needs and circumstances. If you prioritize performance and rapid feature development, then Next.js 13 would be an excellent choice.&lt;/p&gt;

&lt;p&gt;I hope you found this article helpful. Stay tuned for more articles in this series where I’ll be sharing specific coding tips for working with React and Next.js, including how to navigate around common bugs and errors. Happy coding! 😊&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to add internationalization to a Next JS 13 application (with React i18n)</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Sun, 18 Jun 2023 04:19:23 +0000</pubDate>
      <link>https://dev.to/nathlowe/how-to-add-internationalization-to-a-next-js-13-application-with-react-i18n-5glp</link>
      <guid>https://dev.to/nathlowe/how-to-add-internationalization-to-a-next-js-13-application-with-react-i18n-5glp</guid>
      <description>&lt;p&gt;Hey there, fellow developers! Today, we're going to embark on a journey to add internationalization to our Next.js 13 application.&lt;/p&gt;

&lt;p&gt;Picture this: I was knee-deep in a project that needed internationalization, and like any sensible programmer, I turned to our trusty friend Google for help. Lo and behold, I stumbled upon an article that seemed like the perfect solution for my needs. Eagerly, I decided to give it a shot. However, I encountered a series of diverse errors along the way. Let me clarify, the method presented in that article was actually quite solid, but I felt it needed a bit of tweaking. We're not here to reinvent the wheel, though, so I'll save you the trouble of explaining the entire process. If you're curious, you can check out the method I personalized right here: &lt;a href="https://locize.com/blog/next-13-app-dir-i18n/#step-4" rel="noopener noreferrer"&gt;https://locize.com/blog/next-13-app-dir-i18n/#step-4&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why React intl for a NextJS project instead of Next intl ?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of using &lt;code&gt;Next Intl&lt;/code&gt;, I opted for &lt;code&gt;React i18n&lt;/code&gt;. Why, you ask? Well, because in my humble opinion, React i18n is simply the bee's knees! They offer fantastic features like changing the page language via the URL, dividing translation files into namespaces, and, as of now, Next Intl is still in beta.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;First Error&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So, there I was, all excited to get started, and what do I encounter first? "Translation Not Found" error! Turns out, I had been running Next with &lt;code&gt;TurboPack&lt;/code&gt; (also in beta at the time). After nearly an hour of fruitless debugging, I decided to give it a shot with a normal &lt;code&gt;run dev&lt;/code&gt; command. Voila! Problem solved! Note to self: &lt;a href="https://turbo.build/pack/docs" rel="noopener noreferrer"&gt;TurboPack&lt;/a&gt; may not recompile files for every refresh, causing translation issues. But hey, I'm sure the Vercel team will sort it out eventually.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Second Error&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, brace yourself for the worst error of them all: the infamous React Hydration Error! This one really gave me a run for my money. You see, when using the client version of the &lt;code&gt;useTranslation&lt;/code&gt; hook, we need a language value that remains the same on both the server and client sides, at least before hydration kicks in. Now, I had a deep component that I didn't want to burden with passing the language through its parent components. So, I thought, "Why not use a global store?" Cue &lt;code&gt;Zustand&lt;/code&gt;, my trusty companion (you could use context or Redux too, by the way).&lt;/p&gt;

&lt;p&gt;Initially, I set the language value to the default, let's say "en," and in the RootLayout, I passed the "lng" params to a client component to store it. But alas, here's where things got tricky. When the language switched from "en" during SSR to "fr" before hydration, a new value was created for the translation, causing the Hydration Error to rear its ugly head. But fear not, for I found a way out of this predicament.&lt;/p&gt;

&lt;p&gt;Enter the &lt;a href="https://nextjs.org/docs/app/api-reference/functions/use-params" rel="noopener noreferrer"&gt;&lt;code&gt;useParams&lt;/code&gt; hook&lt;/a&gt; of Next.js 13! This magnificent hook retrieves the same params value on both the server and client sides. I utilized it in the component where I wanted to call the &lt;code&gt;useTranslation&lt;/code&gt; hook. But let's be real, adding this to every client component needing translation would be quite the hassle. And what if I decide to change the method later? Nightmare material right there! So, I had a bright idea: I added the &lt;code&gt;useParams&lt;/code&gt; hook to the &lt;code&gt;useTranslation&lt;/code&gt; hook itself. Genius, right? Now, when I call &lt;code&gt;useTranslation&lt;/code&gt;, it automatically invokes &lt;code&gt;useParams&lt;/code&gt;, and guess what? No need to pass the language anymore! I also did away with all the code related to language selection.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;i18n/client.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;i18next
  .use(initReactI18next)
  .use(LanguageDetector)
  .use(resourcesToBackend((language:string, namespace:string) =&amp;gt; import(`../locales/${language}/${namespace}.json`)))
  .init({
    ...getOptions(),
    lng: undefined, // let detect the language on client side
    detection: {
      order: ['path', 'htmlTag', 'cookie', 'navigator'],
    }
  })

const runsOnServerSide = typeof window === 'undefined'

export function useTranslation(ns:string, options={}) {
  const lang = useParams()
  const ret = useTranslationOrg(ns, options)
  const { i18n } = ret
  if (runsOnServerSide &amp;amp;&amp;amp; i18n.resolvedLanguage !== lang.lng) {
    i18n.changeLanguage(lang.lng)
  }
  return ret
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Bug solved!&lt;/em&gt;&lt;/strong&gt; Well, almost.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Final Boss&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, let's talk about that sneaky button I had to change the language on the page. It worked like a charm, thanks to the &lt;code&gt;next/link&lt;/code&gt; component. The only issue? The pages would be prefetched with the current language, meaning the language wouldn't change for the new page we clicked. And to make matters worse, if we kept changing the language continuously, the client components' translation would get stuck in the previous page's language. Yikes!&lt;/p&gt;

&lt;p&gt;But fret not, my fellow adventurers, for I have discovered the solution! I introduced a &lt;code&gt;useEffect&lt;/code&gt; hook to keep an eye on any changes in the language params. Alongside that, I added a state to store the &lt;code&gt;i18n instance&lt;/code&gt; with its trusty translation function (t). By implementing some clever logic, I ensured that when the language changes on the client side, the instance and its translation function change as well. And voila! The translation persists flawlessly in the client components. Crisis averted!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;i18n/client.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
export function useTranslation(ns:string, options={}) {
  const lang = useParams()
  const ret = useTranslationOrg(ns, options)
  const [translation, setTranslation] = useState(ret)
  const { i18n } = translation
  if (runsOnServerSide &amp;amp;&amp;amp; i18n.resolvedLanguage !== lang.lng) {
    i18n.changeLanguage(lang.lng)
  }
  useEffect(()=&amp;gt;{
    if(!runsOnServerSide &amp;amp;&amp;amp; i18n.resolvedLanguage !== lang.lng){
      i18n.changeLanguage(lang.lng)
    }
    setTranslation(state=&amp;gt;({...state,t:i18n.getFixedT(lang.lng, ns)}) )
  },[lang.lng])
  return translation
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like that, we've come to the end of our thrilling internationalization escapade. I hope you enjoyed our little journey and found some useful tips along the way. Thank you for sticking around till the very end. Until next time, happy coding and may your bugs be few and your jokes be plenty! Cheers!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>i18n</category>
    </item>
    <item>
      <title>Building a Social Media Website - Part 2: Ideas and Set up.</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Thu, 18 May 2023 17:58:39 +0000</pubDate>
      <link>https://dev.to/nathlowe/building-a-social-media-website-part-2-ideas-and-set-up-26jh</link>
      <guid>https://dev.to/nathlowe/building-a-social-media-website-part-2-ideas-and-set-up-26jh</guid>
      <description>&lt;p&gt;_Bonjour _and welcome to the second article of our series on building a social media website using NextJS 13, Zustand, Tailwind CSS, Apollo Client, and React i18n. In this article, we'll discuss how we found inspiration for the design of our social media website and go through the setup process to kickstart our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;I- Finding Ideas for the Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To start, we wanted a foundation for our social media website. We discovered a &lt;a href="https://graphqlzero.almansi.me/api" rel="noopener noreferrer"&gt;free GraphQL API&lt;/a&gt; that provides &lt;strong&gt;users&lt;/strong&gt;, &lt;strong&gt;posts&lt;/strong&gt;, &lt;strong&gt;comments&lt;/strong&gt;, &lt;strong&gt;albums&lt;/strong&gt;, and &lt;strong&gt;photos&lt;/strong&gt;. This API is the only one that accepts both Queries and Mutations.&lt;/p&gt;

&lt;p&gt;Then we need to find a matching template for these elements. While exploring various free ones on the internet, we found them to be lacking the specificity we desired. Eventually, we decided to take inspiration from the design of &lt;strong&gt;&lt;a href="https://www.instagram.com/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;&lt;/strong&gt; and made modifications to tailor it to our needs. We began by sketching out the different pages and dividing them into components. Some components would be reused across multiple pages, layouts, as we will see a crucial concept for NextJS 13.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;II- Setting up the Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To begin our coding journey, we'll need a reliable code editor. In this case, we'll use &lt;strong&gt;Visual Studio Code&lt;/strong&gt; (VS Code) due to its popularity and extensive features.&lt;/p&gt;

&lt;p&gt;Next, let's dive into the setup process for our project. First, we need to initialize NextJS 13. Open your terminal or command prompt and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will set up a new NextJS 13 project for us along with Tailwind CSS directly.&lt;/p&gt;

&lt;p&gt;Next, we need to incorporate Zustand for state management, Apollo Client for GraphQL integration, and React i18n for internationalization. Install the necessary packages by running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install zustand apollo-client react-i18next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our project set up, it's important to establish version control. Create a new repository on GitHub and initialize it with the relevant Git commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
git add .
git commit -m "Initial commit"
git remote add origin [repository-url]
git push -u origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, to set the right mood for coding, it's always helpful to have an inspiring playlist🎶. Find your favorite coding playlist or discover a new one that keeps you focused and motivated.&lt;/p&gt;

&lt;p&gt;Now that our foundation is in place, we are ready to move on to the next article, where we will explore &lt;strong&gt;&lt;em&gt;creating routes using NextJS 13&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you liked this article, please consider leave a like and a comment, we will really appreciate it. Stay tuned for the upcoming article and happy coding!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;---NathLowe&lt;/code&gt;&lt;/p&gt;

</description>
      <category>nextjs13</category>
      <category>react</category>
      <category>nextjs</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>How to Learn a New Language or Framework: Tips and Strategies</title>
      <dc:creator>NathLowe</dc:creator>
      <pubDate>Mon, 15 May 2023 21:24:32 +0000</pubDate>
      <link>https://dev.to/nathlowe/how-to-learn-a-new-language-or-framework-tips-and-strategies-1d5f</link>
      <guid>https://dev.to/nathlowe/how-to-learn-a-new-language-or-framework-tips-and-strategies-1d5f</guid>
      <description>&lt;p&gt;Learning a new programming language or framework can be daunting, but it is also an essential skill for any developer. In this series of articles, we will be exploring the process of building a fully responsive social media website using NextJS 13, Zustand, Tailwind CSS, Apollo client, and React i18n. But before we dive into the specifics of these frameworks, let's first discuss some general tips and strategies for learning a new language or framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;I- Master the Fundamentals / Essential Skills&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Understand the Basics of Programming:&lt;/strong&gt;&lt;br&gt;
Before you can effectively learn a new language or framework, you need to have a good understanding of the basics of programming. This includes concepts such as variables, functions, control structures, and data structures. If you're new to programming, consider taking an introductory course or reading a beginner's guide to programming. Personally, as a self-taught, I watched a bunch of training videos on YouTube, and the best channel for me was &lt;em&gt;The Net Ninja&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One must give to Caesar what is Caesar's&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Set Clear Goals&lt;/strong&gt;&lt;br&gt;
When learning a new language or framework, it's important to set clear goals for what you want to achieve. Do you want to build a small project to test out your skills, or do you want to become proficient enough to land a job as a developer? Having clear goals will help you stay motivated and focused on your learning journey. As a freelancer, I usually study new frameworks to improve my curriculum in order to apply for more jobs on Upwork and add more gigs on Fiverr.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Learn by Doing&lt;/strong&gt;&lt;br&gt;
One of the most effective ways to learn a new language or framework is to simply start building things. Choose a small project that you're interested in and use it as an opportunity to practice your new skills. As you work on your project, you'll encounter problems and challenges that will force you to learn new concepts and techniques. This is exactly why I decided to code a social media website, and also because I heard you can't be an accomplished developer without having code this type of website 😅.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use Multiple Resources&lt;/strong&gt;&lt;br&gt;
There are many resources available for learning programming languages and frameworks, including books, online courses, documentation, and forums. Don't limit yourself to just one resource - try to use multiple sources to get a well-rounded understanding of the language or framework you're learning. Personnaly, my first step is to find a free tutorial on YouTube to have a grasp on the framework, and then I read its whole documentation. The first step make the second extremelly lighter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Practice, Practice, Practice&lt;/strong&gt;&lt;br&gt;
Learning a new language or framework takes time and practice. Make sure you're consistently working on projects and practicing your skills. This will help you build your confidence and proficiency over time. It is only practicing over and over that will help the different syntaxes and patterns to get stuck in your brain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The most important in studying a new framework or language is to understant why and how to use it&lt;/strong&gt;, especially for frameworks. The syntaxes, patterns, and functions come after, simply because they will be always available on the documentation to copy. Let me explain what I mean.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;II- Introducing the Frameworks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we've covered some general tips for learning a new language or framework, let's briefly introduce the specific frameworks we'll be using in this series. Most of these are based on React which is a free and open-source front-end JavaScript library for building single page user interfaces based on components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. NextJS 13&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NextJS is a React-based framework for building static-side generated (SSG) and server-side rendered (SSR) web applications. SSG means the code React is converted into an html page with specific style and script files associated once the application is built and can't be changed no more. SSR means the code React is converted into an html page directly on the server everytime the page is requested to this server. And there is more, the 13th version of NextJS add a third type which is Incremental Static Regeneration (ISR). Basically, this make it possible to do an SSG as many times as we decide.&lt;/p&gt;

&lt;p&gt;You may wonder: "&lt;em&gt;Why not just do an SSR instead of ISR ?&lt;/em&gt;" or "&lt;em&gt;What is the specific difference between SSR and SSG anyway ?&lt;/em&gt;". Well, these are legit questions and their understanding is what make the difference between the programmers. However, this is not the purpose of this article, if you want more on NextJS 13, let me know in the comment section.&lt;/p&gt;

&lt;p&gt;So, this is what I meant at the end of the first section. Specifically for this framework, it is essential to know the difference between SSR, SSG, and ISR, between dynamic and static routes, server and client components... How to create those won't be a problem, the only one will be how to use them properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Zustand&lt;/strong&gt;&lt;br&gt;
Zustand is a state management library for React. It allows you to easily manage complex state logic using simple, intuitive hooks. It is easier to use than redux but does it do the job as efficiently as redux does ? We'll find out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Tailwind CSS&lt;/strong&gt;&lt;br&gt;
Tailwind CSS is a utility-first CSS framework that provides pre-defined classes for common styling needs. It allows you to quickly and easily style your application without writing custom CSS. It is easier than Bootstrap to manage and modify. Also, as we don't want to create every single component by ourself, we will use Flowbite components that are based on Tailwind.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We are not lazy just smart 😁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;5. Apollo Client&lt;/strong&gt;&lt;br&gt;
Apollo Client is a framework that helps to manage GraphQL queries and mutations. Read the documentation but mainly the only things we will need is querying datas (GET) and mutating datas (POST, DELETE, UPDATE)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. React i18n&lt;/strong&gt;&lt;br&gt;
React i18n is a library for internationalizing React applications. It provides a simple API for translating your application's text into multiple languages.&lt;/p&gt;

&lt;p&gt;Learning a new language or framework can be challenging, but it is also a rewarding experience that can lead to new career opportunities and personal growth. By following the tips and strategies outlined in this article, you'll be well on your way to mastering your next programming language or framework. In the next article in this series, we'll dive deeper into the specifics of building a social media website using NextJS 13, Zustand, Tailwind CSS, Apollo Client and React i18n.&lt;/p&gt;

&lt;p&gt;Please, if you liked it don't forget to like and subscribe for the other articles of this series. Thank you so much 👨‍💻!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
