<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Charlie Carr</title>
    <description>The latest articles on Forem by Charlie Carr (@char_carr_dev).</description>
    <link>https://forem.com/char_carr_dev</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%2F1012370%2F77a5bab4-7f24-427f-8564-811baeaccf48.jpg</url>
      <title>Forem: Charlie Carr</title>
      <link>https://forem.com/char_carr_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/char_carr_dev"/>
    <language>en</language>
    <item>
      <title>👨‍💻 🤖 Next 13 Overview &amp; Building in Public 🛠️ 🚀</title>
      <dc:creator>Charlie Carr</dc:creator>
      <pubDate>Thu, 10 Aug 2023 17:47:37 +0000</pubDate>
      <link>https://forem.com/char_carr_dev/next-13-overview-building-in-public-50jg</link>
      <guid>https://forem.com/char_carr_dev/next-13-overview-building-in-public-50jg</guid>
      <description>&lt;p&gt;This blog post is reposted from my personal &lt;a href="https://charliecarr.dev/blog" rel="noopener noreferrer"&gt;blog&lt;/a&gt; (check it out &lt;a href="https://charliecarr.dev/blog/next-tennis-one" rel="noopener noreferrer"&gt;here&lt;/a&gt; for a better reading experience using MDX components). &lt;/p&gt;

&lt;p&gt;This is the start of a new blog series that focuses on new Next.js features and building in public. Follow along with my GitHub &lt;a href="https://github.com/CharlesCarr/grand-slams-dashboard" rel="noopener noreferrer"&gt;repo&lt;/a&gt; and see the live app hosted on Vercel &lt;a href="https://grand-slams-dashboard.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro to Next.js 13 (13.4)&lt;/li&gt;
&lt;li&gt;React vs. Next.js&lt;/li&gt;
&lt;li&gt;Quick Highlights on Next 13&lt;/li&gt;
&lt;li&gt;Building &amp;amp; Learning in Public&lt;/li&gt;
&lt;li&gt;Feature Spotlight: Server Components&lt;/li&gt;
&lt;li&gt;Feature Spotlight: App Router&lt;/li&gt;
&lt;li&gt;Feature Spotlight: Data Fetching&lt;/li&gt;
&lt;li&gt;Some Final Thoughts&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Links to Code and Live App
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/CharlesCarr/grand-slams-dashboard" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grand-slams-dashboard.vercel.app/" rel="noopener noreferrer"&gt;Live Application&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Intro to Next.js 13 (13.4) &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Next.js is a React framework for building full-stack web applications. Since its inception in 2016 by the team at Vercel, it has rapidly ascended the ladder of popularity in the world of web development.&lt;/p&gt;

&lt;p&gt;Some of its key features include built in file-system routing, client and server side rendering, api routes, and automatic code splitting.&lt;/p&gt;

&lt;p&gt;React developers opt for Next as it presents &lt;strong&gt;key benefits&lt;/strong&gt; such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimizations and improved initial loading times&lt;/strong&gt; - code splitting, incremental static regeneration, image optimizations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Additional SEO support&lt;/strong&gt; - improved scoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stronger dev experience&lt;/strong&gt; - not needing to add routing libs, no longer need to set up a separate backend server - as now both front end and back end live in Next&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next.js has been widely adopted by major corporations such as Netflix, TikTok, and Uber leveraging its capabilities to drive their web experiences.&lt;/p&gt;

&lt;p&gt;In late 2022, Vercel released Next 13 bringing on major changes to support the new React 18 paradigm (client / server components) and most notably the introduction to the &lt;code&gt;/app&lt;/code&gt; directory/router that was recently declared stable by the team this May.&lt;/p&gt;

&lt;p&gt;This article (and those to follow in this series) will unpack these newer Next.js 13 features and other supplemental technologies through the lens of building a professional tennis web application.&lt;/p&gt;




&lt;h2&gt;
  
  
  But first.. React vs. Next.js &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A quick table here to share for those who are looking to clearly compare React and Next.js as a quicker refresher before diving deeper.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;/th&gt;
&lt;th&gt;React&lt;/th&gt;
&lt;th&gt;Next.js&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Definition&lt;/td&gt;
&lt;td&gt;A JavaScript library for building user interfaces&lt;/td&gt;
&lt;td&gt;Full stack React framework for the web&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rendering&lt;/td&gt;
&lt;td&gt;Client Side rendering - larger bundle sizing on client&lt;/td&gt;
&lt;td&gt;Sever Side Rendering / Static Site Generation make for very performant web apps - less JavaScript on client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routing&lt;/td&gt;
&lt;td&gt;No built in routing - must rely on external libs&lt;/td&gt;
&lt;td&gt;Built in file system based routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Splitting&lt;/td&gt;
&lt;td&gt;No code splitting - poorer performance&lt;/td&gt;
&lt;td&gt;Automatic code splitting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO Friendly&lt;/td&gt;
&lt;td&gt;Slightly SEO friendly&lt;/td&gt;
&lt;td&gt;Way more SEO friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image Optimization&lt;/td&gt;
&lt;td&gt;Not built in but can use external libs&lt;/td&gt;
&lt;td&gt;Image optimizations with next/image component&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Education / Community&lt;/td&gt;
&lt;td&gt;Faster to pick up with larger community/documentation&lt;/td&gt;
&lt;td&gt;Prior knowledge of React required with smaller community/documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configurability&lt;/td&gt;
&lt;td&gt;Basic adjustments needed for configurations&lt;/td&gt;
&lt;td&gt;Everything can be configured with ease&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed&lt;/td&gt;
&lt;td&gt;Slower than Next&lt;/td&gt;
&lt;td&gt;Faster than vanilla React&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Quick Highlights on Next 13's New Features &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;New Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App Directory / Router&lt;/strong&gt; - file based routing and colocation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Server Components&lt;/strong&gt; - async components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layouts&lt;/strong&gt; - new shared UI wrappers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Fetching&lt;/strong&gt; - w/ caching, revalidation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming&lt;/strong&gt; - server sending smaller bits to client&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turbopack&lt;/strong&gt; - new much faster build tool (alt to Webpack)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toolkit Updates&lt;/strong&gt; - image, font, link optimizations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OG Image Generation&lt;/strong&gt; - open graph imgs for dynamic social cards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middleware API&lt;/strong&gt; - better dev exp and new functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, I will introduce the major new capabilities of Next 13 and will dive deeper into more in future articles of this series.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beginning this Blog Series and Building / Learning in Public &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After building my latest freelance client’s web application with Next 13’s pages router, I decided to build my next independent application with the newly stable app router. As I follow the #buildinpublic community on Twitter and am a big fan of the Indie Hacking community, I came up with the idea to rather than build this independently for my own benefit to instead share my learnings along the way.&lt;/p&gt;

&lt;p&gt;As I started mapping out this application, I came across &lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;shadcn/ui&lt;/a&gt; re-usable components and his example dashboard. I found an interesting dataset on tennis grand slam finals results and quickly spun up a Supabase Postgres DB with tables to serve the data for my own dashboard to display this data in interesting ways for tennis fans.&lt;/p&gt;

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

&lt;p&gt;Over the coming days and weeks, I will continue building out this application and will be sharing my learnings and process along the way through these blog posts and tweets (my Twitter handle is &lt;a href="https://twitter.com/charcarr04" rel="noopener noreferrer"&gt;@charcarr04&lt;/a&gt;). I will see how far I can take this leading up to this year’s US Open and hopefully refine some skills along the way and share with the dev community.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Feature Spotlight&lt;/strong&gt; - Server Components &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before diving into Next 13.4, it is important to understand the new mental model of React 18’s client and server components. As discussed in the table above, the previous model of React (without added frameworks) was that everything was rendered on the client in SPAs. The creation of server components has created a hybrid approach where there are components that are rendered completely on the server and those that can be rendered on the client.&lt;/p&gt;

&lt;p&gt;This new approach combines the rich interactivity of client-side apps with the improved performance of traditional server rendering.&lt;/p&gt;

&lt;p&gt;The way I think about this is that everything is a server component unless it needs to be on the client (client interactivity (buttons/inputs), browser APIs, state / lifecycle methods - hooks, etc). This new paradigm reminds me of my earlier days learning to code with PHP. Now things like data fetching (discussed in more detail below) and other pieces of code that would traditionally bulk up the bundle size are moved to the server. This has positive results of more performant web applications including faster initial page load speeds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;TourSelect&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tourSelect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModeToggle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/mode-toggle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DashHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col-reverse sm:flex-row w-full justify-between items-center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-4xl sm:text-4xl font-bold tracking-tight  mt-4 sm:mt-0"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Grand Slam Titles
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center gap-3"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TourSelect&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ModeToggle&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;DashHeader is a server component as all components inside of &lt;code&gt;/app&lt;/code&gt; are server by default. This component renders only static content from the server but has two client components inside of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SelectContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SelectItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SelectTrigger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SelectValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/ui/select&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jotai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tourAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TourSelect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTour&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tourAtom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setTour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SelectTrigger&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-[130px] text-xs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SelectValue&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SelectTrigger&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SelectContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SelectItem&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mens"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Mens (ATP)
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SelectItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SelectItem&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"womens"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Womens (WTA)
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SelectItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SelectContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Components can then be turned into "client components" by adding the ‘use client’ directive at top of the component. TourSelect uses client side state and has user interactivity for selecting the mens or womens tour to then display the appropriate tour data. These traits require it to be a client component.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Feature Spotlight&lt;/strong&gt; - App Router &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;One of Next.js 13's most significant updates is the App Router, designed to be the long-term path for Next.js development. While the pages router isn't going anywhere (the Vercel team will still continue to support and add new features), they're nudging new projects towards embracing the App Router as it is the long term vision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding the App Router:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; &lt;strong&gt;File-system based routing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just as with the pages router, each folder represents a route segment, directly correlating to a corresponding segment in the URL path. This extends even to nested routes within folders.&lt;/p&gt;

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

&lt;p&gt;In my app router folder structure, I have the routes (admin, dashboard, player). I then colocate my files (components and hooks) for the specific routes and have more general components (ui, etc) that live outside of my app router. This is not the definitive way to set up the Next.js folder structure but just one way that has worked well for this tennis app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. File conventions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As stated before, all files within the app router are by default server components. The most important file for each folder is the &lt;strong&gt;&lt;code&gt;page.tsx&lt;/code&gt;&lt;/strong&gt;. This creates the UI for a given route and also make those routes publicly accessible.&lt;/p&gt;

&lt;p&gt;The second most important file is &lt;strong&gt;&lt;code&gt;layout.tsx&lt;/code&gt;&lt;/strong&gt; which is a UI component that is shared between multiple pages that serves as a wrapper for your page and other components. Layouts accept a children prop that will be populated with a child page for rendering.&lt;/p&gt;

&lt;p&gt;Other files that are important to know include: loading, not-found, and error (may go into more detail on these in future blog articles).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Colocation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This concept is foundational to the App Router (and probably my favorite aspect). It allows developers to house relevant files – be it components, styles, tests, or more – within these route folders. This was not possible in the pages directory as any file in pages is considered a route. Now, only the &lt;code&gt;page.tsx&lt;/code&gt; files are publicly accessible, ensuring a neat and organized structure.&lt;/p&gt;

&lt;p&gt;(*Note: Colocating your project files is not manditory and these files can live outside of &lt;code&gt;/app&lt;/code&gt; if preferred)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigating the Routes:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigating within the App Router can be achieved in two distinct ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Link component:&lt;/strong&gt; Acting as an extension to the traditional HTML &lt;strong&gt;&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;&lt;/strong&gt; tag, this is the go-to method to navigate in Next.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;useRouter hook:&lt;/strong&gt; This hook (now imported from &lt;strong&gt;&lt;code&gt;next/navigation&lt;/code&gt;&lt;/strong&gt;) is useful for when programmatic route changes are necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Performance – The Hybrid Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The App Router marries the efficiency of server-side code splitting per route segment with the finesse of client-side route segment prefetching and caching. When a user ventures to a new route, there's no page reload - only the altered route segments get a makeover, offering a seamless and performant navigation experience.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prefetching:&lt;/strong&gt; This mechanism preloads routes in the background before they're actively visited. The Link component will auto-prefetch when they become visible in the user's viewport. And if you've got the itch to prefetch manually, &lt;strong&gt;&lt;code&gt;router.prefetch()&lt;/code&gt;&lt;/strong&gt; is at your service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching:&lt;/strong&gt; Say hello to Next's in-memory client-side cache, termed the Router Cache. As users navigate, the React Server Component Payload of prefetched and previously visited route segments are stored in this cache. This cache is used as much as possible - minimizing redundant server requests and data transfer, enhancing performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Dynamic Routes:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dynamic routes take a bit of a different approach with Next 13’s app router. For scenarios where exact segment names come from dynamic data, you can enclose a folder's name in square brackets, for instance, &lt;strong&gt;&lt;code&gt;[id]&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;[slug]&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These Dynamic Segments and the &lt;strong&gt;&lt;code&gt;generateStaticParams&lt;/code&gt;&lt;/strong&gt; function used together statically generate routes at build time instead of on-demand at request time. This new function’s smart retrieval of data benefits applications with automatic memoization. This means a &lt;code&gt;fetch&lt;/code&gt; request with the same arguments across multiple &lt;code&gt;generateStaticParams&lt;/code&gt;, Layouts, and Pages will only be made once, which decreases build times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/utils/supabase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notFound&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DataTable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../components/data-table&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../components/columns&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getSlamInfo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/dashboard/utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BackButton&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../components/back-btn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ProfileInfo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../components/profile-info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateStaticParams&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;atp_players&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Return empty array if no players&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;playerData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;atp_players&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;playerResults&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grand_slam_mens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`champion_id.eq.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,runner_up_id.eq.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;major_number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;playerData&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;playerResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playerResultsWithMajorName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transformedMajor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getSlamInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;major_number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;major_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;transformedMajor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tournament&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;seed_champ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed_champion&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed_champion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;seed_runner_up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed_runner_up&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed_runner_up&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;champion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;champion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; `&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;seed_champ&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner_up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runner_up&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; `&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;seed_runner_up&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container mx-auto py-10"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BackButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl sm:text-4xl font-bold tracking-tight mt-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Grand Slam Titles:
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-muted-foreground ml-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;playerData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;player_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProfileInfo&lt;/span&gt; &lt;span class="na"&gt;playerData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;playerData&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;playerResults&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;playerResults&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DataTable&lt;/span&gt; &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;playerResultsWithMajorName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a server component in my tennis app where I am dynamically generating the mens (ATP) players profile pages. I am using Supabase for my DB so instead of a fetch to my own backend I am querying the 'id' column of my 'atp_players' table. The generateStaticParams function creates all of the paths for each player based on their 'id' and then in my async server component I am retrieving this id from the params to query the player's additional profile data to render on the player profile page.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Feature Spotlight&lt;/strong&gt; - Data Fetching &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Next 13 provides new features for fetching data from the server. It has extended the native fetch Web API with additional caching and revalidation configurations. Each fetch request is memoized while rendering the React component tree.&lt;/p&gt;

&lt;p&gt;My previous example with the server component from my dynamic mens players route is a good example of these async / await features in action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;playerData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;atp_players&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than needing to use React lifecycle hooks and handle this on the client, server components simplify the data fetching process. Now you only need to mark the component as async and then await the fetched data directly in the component. This leads to much cleaner code and this would work the same way if I was using the fetch API instead of querying directly from Supabase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next.js automatically caches the returned values of the fetch request on the server. Data can then be fetched at build time or request time, cached, and reused on each data request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revalidation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you are looking to return the latest data from the server Next provides the ability to customize revalidation. Revalidation will clear the cached data and refetch to ensure that the app is returning the most up to date information to its users. There are two main approaches for this - time-based revalidation (automatically revalidate data after a set time interval) and on-demand validation (manually revalidating data based on event - good for form submissions).&lt;/p&gt;




&lt;h2&gt;
  
  
  Some Final Thoughts &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The new Next.js 13 features have been a great developer experience for me so far and I am looking forward to building and sharing more in my next article in the series.&lt;/p&gt;

&lt;p&gt;Let me know in the comments what other Next 13 aspects you would like to see / other ideas for features of this app. &lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

&lt;p&gt;Charlie&lt;/p&gt;

&lt;p&gt;&lt;a href="https://charliecarr.dev" rel="noopener noreferrer"&gt;My Website&lt;/a&gt;&lt;br&gt;
&lt;a href="https://charliecarr.dev/blog" rel="noopener noreferrer"&gt;My Blog&lt;/a&gt;&lt;br&gt;
&lt;a href="https://charliecarr.dev/blog/next-tennis-one" rel="noopener noreferrer"&gt;Original Post&lt;/a&gt;&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>react</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>6 Approaches for Data Fetching in React</title>
      <dc:creator>Charlie Carr</dc:creator>
      <pubDate>Tue, 31 Jan 2023 00:29:11 +0000</pubDate>
      <link>https://forem.com/char_carr_dev/6-approaches-for-data-fetching-in-react-1ec3</link>
      <guid>https://forem.com/char_carr_dev/6-approaches-for-data-fetching-in-react-1ec3</guid>
      <description>&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intro to Data Fetching in React&lt;/li&gt;
&lt;li&gt;Simple Explanation of JavaScript Promises&lt;/li&gt;
&lt;li&gt;Approach #1: Fetch API w/ Promise Methods&lt;/li&gt;
&lt;li&gt;Approach #2: Axios Library w/ Promise Methods&lt;/li&gt;
&lt;li&gt;Approach #3: Async Functions (async / await)&lt;/li&gt;
&lt;li&gt;Approach #4: Creating ‘useFetch’ Custom React Hook&lt;/li&gt;
&lt;li&gt;Approach #5: React Query Library&lt;/li&gt;
&lt;li&gt;Approach #6: Redux Toolkit’s RTK Query&lt;/li&gt;
&lt;li&gt;Some Final Thoughts&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Link to Follow Along w/ Examples
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/CharlesCarr/react-data-fetch" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Data Fetching in React &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Data fetching is a core aspect of any React application. It is very important for React developers to understand the different data fetching approaches and which is most appropriate for their use case.&lt;/p&gt;

&lt;p&gt;This article has a corresponding &lt;a href="https://github.com/CharlesCarr/react-data-fetch" rel="noopener noreferrer"&gt;public GitHub repository&lt;/a&gt; that you can reference to better understand. The sample React app fetches data from an external API &lt;a href="https://random.dog/" rel="noopener noreferrer"&gt;(random.dog)&lt;/a&gt; and renders a random picture of a dog on the webpage. Its goal is to be very simple to allow for easy comparison between the data fetching approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  But first, let's understand JavaScript Promises &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Simply put, a promise is a JavaScript object that will produce a value sometime in the future. This usually applies to asynchronous operations (ex. data fetching). &lt;/p&gt;

&lt;p&gt;A promise has three states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pending&lt;/strong&gt;: where the promise is still in the works &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fulfilled&lt;/strong&gt;: where the promise resolves successfully and returns a value &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected&lt;/strong&gt;: where the promise fails with an error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a promise is fulfilled or rejected it has &lt;strong&gt;settled&lt;/strong&gt;. Promises have different methods for doing different things depending on the outcome. These methods will be discussed in greater detail in the next sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Approach #1&lt;/strong&gt; - Fetch API w/ Promise Methods &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The Fetch API provides a global &lt;code&gt;fetch()&lt;/code&gt; method that enables developers a straightforward approach to fetching data. Prior to &lt;code&gt;fetch()&lt;/code&gt;, the conventional approach was using &lt;code&gt;XMLHttpRequest()&lt;/code&gt;. (&lt;em&gt;This approach is not included in this article as &lt;code&gt;fetch()&lt;/code&gt; has replaced it with a more powerful and flexible feature set.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fetch()&lt;/code&gt; method requires one parameter, the &lt;strong&gt;URL&lt;/strong&gt; to request, and returns a promise. The second and optional parameter, &lt;strong&gt;options&lt;/strong&gt;, is an array of properties. The return value of &lt;code&gt;fetch()&lt;/code&gt; can be either JSON or XML (either an array of objects or a single object). Without the &lt;strong&gt;options&lt;/strong&gt; parameter, &lt;code&gt;fetch()&lt;/code&gt; will always make a &lt;strong&gt;GET&lt;/strong&gt; request.&lt;/p&gt;

&lt;p&gt;This first approach is what you will typically see in simple use cases of data fetching and often the first result when navigating API documentation. As stated before, we are fetching data from an API that returns a random image of a dog and we then render that image on screen. Prior to making the request, we wrap the code inside a &lt;code&gt;useEffect&lt;/code&gt; hook with an empty dependency array to run the &lt;code&gt;fetch()&lt;/code&gt; method only when the component initially mounts.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://github.com/CharlesCarr/react-data-fetch/blob/main/src/components/ExampleOne.jsx" rel="noopener noreferrer"&gt;Full Code for Approach #1&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// syntax for handling promises&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// check to see if response is okay&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// if okay, take JSON and parse to JavaScript object&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="c1"&gt;//  .json() returns a promise as well&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// setting response as the data state&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="c1"&gt;// if res is not okay the res is thrown here for error&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// setting the error state&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="c1"&gt;//  regardless if promise resolves successfully or not we remove loading state&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Inside the &lt;code&gt;useEffect&lt;/code&gt; we call the &lt;code&gt;fetch()&lt;/code&gt; method and pass in the URL for our API endpoint. In this approach we are using the &lt;code&gt;.then()&lt;/code&gt;, &lt;code&gt;.catch()&lt;/code&gt;, &lt;code&gt;.finally()&lt;/code&gt; methods of a promise object (recall that &lt;code&gt;fetch()&lt;/code&gt; returns a promise). We use the &lt;code&gt;.then()&lt;/code&gt; method and pass in a callback function to check if the response is ok. If the response is ok, we take the JSON data that is returned and parse it into a JavaScript object with the &lt;code&gt;.json()&lt;/code&gt; method. If the response is not ok, we &lt;code&gt;throw&lt;/code&gt; an error. &lt;/p&gt;

&lt;p&gt;Since the &lt;code&gt;.json()&lt;/code&gt; method also returns a promise we can chain another &lt;code&gt;.then()&lt;/code&gt; and pass a function that sets the state of the data to then be used elsewhere in the component. In our example, the external API returns an object with a url property (will be used as &lt;code&gt;src&lt;/code&gt; of our image).&lt;/p&gt;

&lt;p&gt;Continuing through the chain, the next section is the &lt;code&gt;.catch()&lt;/code&gt; that schedules a function to be called when the promise is rejected. This also returns another promise where we can then chain the &lt;code&gt;.finally()&lt;/code&gt; method that will be called regardless of if the promise is settled (either resolved or rejected). The &lt;code&gt;.finally()&lt;/code&gt; method allows us to avoid duplicating code in both &lt;code&gt;.then()&lt;/code&gt; and &lt;code&gt;.catch()&lt;/code&gt;, making this a good place to remove the loading state in our example.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Approach #2&lt;/strong&gt; - Axios Library w/ Promise Methods &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Axios is a popular HTTP client library that can be used for efficient data fetching. It can be easily installed via npm or other package managers into React applications. Using Axios is an alternative to the Fetch API and has some advantages if you do not mind installing an external library.&lt;/p&gt;

&lt;p&gt;This second example will be very close to our code for the first example using the same promise methods for handling promise state and responses. Instead of using the &lt;code&gt;fetch()&lt;/code&gt; method, after importing the Axios library into our component we can use the &lt;code&gt;axios.get()&lt;/code&gt; method where we can pass in the URL to our external API endpoint. This will return a promise so we can take the same approach with the promise method chaining.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://github.com/CharlesCarr/react-data-fetch/blob/main/src/components/ExampleTwo.jsx" rel="noopener noreferrer"&gt;Full Code for Approach #2&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// syntax for handling promises&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// axios converts json to object for us (shortens our code)&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="c1"&gt;// axios takes care of error handling for us instead of checking manually&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// setting the error state&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="c1"&gt;//  regardless if promise resolves successfully or not we remove loading state&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The apparent differences between the code for the Fetch API and the code for this Axios approach is that with Axios we only need a single &lt;code&gt;.then()&lt;/code&gt; as Axios converts the JSON to a JavaScript object for us (shortening our code). Additionally, we are no longer writing a conditional to throw errors manually because Axios throws 400 and 500 range errors for you (again shortening our code).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Approach #3&lt;/strong&gt; - Async Functions (async / await)
&lt;/h2&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example we will be moving away from the promise chaining we have used in the previous two examples and instead introduce a more modern approach for writing asynchronous, promise-based code. This approach can be used with whatever fetching mechanism you choose but for this example we will be sticking with the Axios library.&lt;/p&gt;

&lt;p&gt;This third example sets up the component in a similar way to the last example with importing the Axios library and then wrapping the code for fetching the data inside of a &lt;code&gt;useEffect&lt;/code&gt; with an empty dependency array. Within the &lt;code&gt;useEffect&lt;/code&gt;, we create an asynchronous function using the &lt;code&gt;async&lt;/code&gt; keyword and then within the function have three separate sections - &lt;code&gt;try&lt;/code&gt;, &lt;code&gt;catch&lt;/code&gt;, and &lt;code&gt;finally&lt;/code&gt;. This try/catch approach is used to handle errors in JavaScript. The code inside of the &lt;code&gt;try&lt;/code&gt; block is executed first and if there are any errors thrown they will be ‘caught’ in the &lt;code&gt;catch&lt;/code&gt; block and the code inside will be executed. Lastly, the &lt;code&gt;finally&lt;/code&gt; block will always be executed after the flow passes through the try/catch.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://github.com/CharlesCarr/react-data-fetch/blob/main/src/components/ExampleThree.jsx" rel="noopener noreferrer"&gt;Full Code for Approach #3&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// create async function b/c cannot use async in useEffect arg cb&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//   with async/await use the try catch block syntax for handling&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// using await to make async code look sync and shorten &lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// setting the error state&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In this example, the &lt;code&gt;try&lt;/code&gt; block creates a variable called &lt;code&gt;res&lt;/code&gt; (short for response) that uses the &lt;code&gt;async&lt;/code&gt; keyword. This allows the code to look synchronous (shorter and easier on the eyes). In this example the &lt;code&gt;axios.get(URL)&lt;/code&gt; is being ‘awaited’ until it settles. If the promise is fulfilled, then we set the data into the state. If the promise is rejected (errors thrown), it moves into the &lt;code&gt;catch&lt;/code&gt; block.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Approach #4&lt;/strong&gt; - Creating ‘useFetch’ Custom React Hook
&lt;/h2&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fourth approach is creating our own custom React hook called &lt;code&gt;useFetch&lt;/code&gt; that will be able to be reusable across our app in different components and cut out the bulky fetching code from each component. This example is really just taking the fourth example (same technique of using the Axios library with async/await) and moving that code into its own custom hook.&lt;/p&gt;

&lt;p&gt;To do this, we create a new file called &lt;code&gt;useFetch.js&lt;/code&gt;. We then take all of the code within the &lt;code&gt;useEffect&lt;/code&gt; from the last example as well as the different states we are tracking add it inside of the &lt;code&gt;useFetch&lt;/code&gt; function. Finally this function will return an object with each of those states to then be accessed where the &lt;code&gt;useFetch&lt;/code&gt; hook is called. Our &lt;code&gt;useFetch&lt;/code&gt; hook will also accept one parameter, the &lt;strong&gt;URL&lt;/strong&gt;, to allow for more reusability with the potential to make fetch requests to different endpoints.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://github.com/CharlesCarr/react-data-fetch/blob/main/src/hooks/useFetch.js" rel="noopener noreferrer"&gt;Full Code for Approach #4&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useFetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// create async function b/c cannot use asyc in useEffect arg cb&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;//   with async/await use the try catch block syntax for handling&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// using await to make async code look sync and shorten&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// setting the error state&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

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

&lt;/div&gt;






&lt;p&gt;Finally, we import this new custom hook into the components where it will be used and then call it as we would any other React hook. As you can see this greatly helps with code readability and shortening our component.&lt;/p&gt;

&lt;p&gt;One final note with this approach is that there are also external libraries that you can install rather than creating your own custom hook. One popular library is &lt;code&gt;react-fetch-hook&lt;/code&gt; with a very similar functionality to the hook we just built.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Approach #5&lt;/strong&gt; - React Query Library
&lt;/h2&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the most modern and robust approaches for data fetching in React is using the React Query library. It has many features in addition to just simple data fetching but for this example we will learn just how to simply fetch data from the same example external API. (&lt;em&gt;If you are interested in learning more check it out &lt;a href="https://react-query-v3.tanstack.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;After installing and importing, React Query provides many custom hooks that can be reused across our components in a very concise way. In this example, we &lt;code&gt;import&lt;/code&gt; &lt;code&gt;QueryClient&lt;/code&gt; and &lt;code&gt;QueryClientProvider&lt;/code&gt; from &lt;code&gt;react-query&lt;/code&gt; and then wrap our application with the provider and pass the &lt;code&gt;queryClient&lt;/code&gt; instance as the &lt;code&gt;client&lt;/code&gt; property to the wrapper. This enables us to use the library across our app.&lt;/p&gt;

&lt;p&gt;To make this simple GET request we import and use the &lt;code&gt;useQuery&lt;/code&gt; hook. Unlike the previous example with our custom hook, we pass in two parameters. The first required parameter is the &lt;strong&gt;queryKey&lt;/strong&gt; that is used as a key for reference for this specific query. The second required parameter is the &lt;strong&gt;queryFn&lt;/strong&gt; that is the function that the query will use to request data. Rather than just passing in a simple URL like our previous custom hook example we will use this query function and then use the Fetch API and promise method syntax to make the initial fetch. (&lt;em&gt;This hook has many other optional parameters.&lt;/em&gt;)&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://github.com/CharlesCarr/react-data-fetch/blob/main/src/components/ExampleFive.jsx" rel="noopener noreferrer"&gt;Full Code for Approach #5&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dogData&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;From here, React Query will do all of the additional work behind the scenes and in this example we can destructure &lt;code&gt;isLoading&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;data&lt;/code&gt; from this hook call to be used in our application although there are many other values we are able to access as well.&lt;/p&gt;

&lt;p&gt;The power and advantages of using React Query are evident in examples that are larger than our current Dog Image API example. A few additional features to mention include: caching, updating ‘out of date’ data in the background, and other performance related benefits. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Approach #6&lt;/strong&gt; - Redux Toolkit’s RTK Query &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The final approach of this article is data fetching with Redux Toolkit’s RTK Query. It is very common for apps to be using Redux for state management. If your company or your current side project is currently using Redux, a good option is to use RTK Query for data fetching as it provides similar simplicity and benefits as React Query does.&lt;/p&gt;

&lt;p&gt;To start using RTK Query wherever you are storing your Redux code, create a &lt;code&gt;rtkQueryService.js&lt;/code&gt; file that will be the setup for data fetching. After creating you then add the service to your Redux store and assuming you are already using Redux you will already have a &lt;code&gt;&amp;lt;Provider&amp;gt;&lt;/code&gt; component with the store that is wrapped around your application. &lt;/p&gt;

&lt;p&gt;From here, it is very similar to using the custom hook and React Query approach where you import and then use the query hook and destructure &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;isLoading&lt;/code&gt; to then be able to use in your component.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;a href="https://github.com/CharlesCarr/react-data-fetch/blob/main/src/components/ExampleSix.jsx" rel="noopener noreferrer"&gt;Full Code for Approach #6&lt;/a&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetDogQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;As you can see there is a lot of setup for Redux so this might not be the best approach for our use case but RTK Query can be valuable if you are already using Redux within your React app and want a simple and modern approach for data fetching that also provides benefits like caching.&lt;/p&gt;




&lt;h2&gt;
  
  
  Some Final Thoughts &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Props to you if you got to this point! The goal of this article was to introduce some different approaches of data fetching for those learning React. This serves as a centralized place to compare with the same use case to better understand. It was not my goal to make statements on the ‘best’ approach or dive into granular detail.&lt;/p&gt;

&lt;p&gt;Additionally, there are other current approaches to data fetching not mentioned here and I am sure others will come about as the React ecosystem evolves. That said, I believe this article provides a strong foundation for understanding this space. I hope you found this useful!&lt;/p&gt;




&lt;p&gt;(&lt;em&gt;As this was my first post on dev.to I am curious to hear your feedback in the comments! What is your preferred way to fetch data in your React apps?&lt;/em&gt;)&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.charlie-carr.com/" rel="noopener noreferrer"&gt;charlie-carr.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>offers</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
