<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ routing - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ routing - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 23 Jun 2026 22:45:02 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/routing/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Routing and Multi-Screen Development in Flutter – a Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Modern mobile applications are far from static, single-view experiences. Instead, they are dynamic, multi-faceted environments where users seamlessly transition between different features, content, and functionalities. Because of this inherent comple... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/routing-and-multi-screen-development-in-flutter-for-beginners/</link>
                <guid isPermaLink="false">685d7ca925e1a316c88035e8</guid>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ flutter-aware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Atuoha Anthony ]]>
                </dc:creator>
                <pubDate>Thu, 26 Jun 2025 17:00:25 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750956717640/60bc5ee7-640d-4d8c-8b8d-64e422fadf56.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Modern mobile applications are far from static, single-view experiences. Instead, they are dynamic, multi-faceted environments where users seamlessly transition between different features, content, and functionalities. Because of this inherent complexity, you’ll need to set up robust routing as well as a well-designed multi-screen architecture.</p>
<p>In this tutorial, you'll learn about Flutter's fundamental navigation systems: Imperative Navigation (<code>Navigator.push</code>/<code>pop</code>) and Named Routes. We'll explore their practical implementation through building an example Car List app. Through this process, you’ll learn how to navigate between a list of cars and their detailed views, and how to pass data between screens.</p>
<p>By the end, you'll gain a solid understanding of how to manage navigation stacks and create a smooth user experience in your Flutter applications.</p>
<h3 id="heading-table-of-contents"><strong>Table of Contents</strong></h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-should-you-build-multi-screen-apps">Why Should You Build Multi-Screen Apps?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-flutters-navigation-systems">Flutter's Navigation Systems</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-simple-navigator-api-navigatorpush">The Simple Navigator API: Navigator.push</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-named-routes-the-scalable-approach">Named Routes: The Scalable Approach</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-backstack-management-controlling-user-flow">Backstack Management: Controlling User Flow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-organization-tips-for-scalable-navigation">Code Organization Tips for Scalable Navigation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-scalable-navigation-when-built-in-isnt-enough">Scalable Navigation: When Built-in Isn't Enough</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-flutter-project-the-car-list-app">How to Set Up Your Flutter Project: The Car List App</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most out of this tutorial, you should have:</p>
<ul>
<li><p><strong>Basic understanding of the Dart programming language:</strong> Familiarity with concepts like variables, data types, functions, classes, and asynchronous programming.</p>
</li>
<li><p><strong>Fundamental knowledge of Flutter widgets:</strong> Knowing how to use <code>StatelessWidget</code>, <code>StatefulWidget</code>, and basic layout widgets like <code>Column</code>, <code>Row</code>, <code>Container</code>, and <code>Text</code>.</p>
</li>
<li><p><strong>Flutter SDK installed and configured:</strong> Ensure you have a working Flutter development environment set up on your machine.</p>
</li>
<li><p><strong>A code editor:</strong> Visual Studio Code or Android Studio with Flutter and Dart plugins installed.</p>
</li>
</ul>
<h2 id="heading-why-should-you-build-multi-screen-apps">Why Should You Build Multi-Screen Apps?</h2>
<p>Real-world apps are rarely single-screen. Imagine a banking app that only shows your balance, or a social media app that only displays your feed. It's simply not practical.</p>
<p>Users expect to be able to:</p>
<ul>
<li><p>View a list of items (for example, cars, products, news articles).</p>
</li>
<li><p>Tap on an item to see its detailed information.</p>
</li>
<li><p>Access user profiles, settings, or shopping carts.</p>
</li>
<li><p>Complete multi-step processes like checkout or onboarding.</p>
</li>
</ul>
<p>This intricate dance between different views highlights that navigation is a core user experience component. A fluid, intuitive, and predictable navigation flow directly translates to improved user satisfaction and maintainability for developers. Confusing navigation, on the other hand, can quickly lead to user frustration and abandonment.</p>
<h2 id="heading-flutters-navigation-systems">Flutter's Navigation Systems</h2>
<p>Flutter provides powerful and flexible navigation mechanisms, catering to various application complexities. At a high level, we can categorize these mechanisms in the following ways:</p>
<ol>
<li><p><strong>Imperative Navigation (Navigator.push / pop):</strong> This is the most basic and direct way to control the navigation stack. You explicitly tell the <code>Navigator</code> to push a new route or pop the current one.</p>
</li>
<li><p><strong>Named Routes:</strong> A more structured approach where routes are identified by string names, allowing for centralized configuration.</p>
</li>
<li><p><code>onGenerateRoute</code> / <code>onUnknownRoute</code>: Advanced callbacks within <code>MaterialApp</code> or <code>WidgetsApp</code> that provide fine-grained control over how routes are generated, especially useful for dynamic or deep linking scenarios.</p>
</li>
<li><p><strong>Declarative Navigation (for example,</strong> <code>go_router</code>, <code>Beamer</code>): For highly complex apps with deep linking, nested navigation, and web support, declarative packages offer a more state-driven approach to routing, where the URL or app state defines the current screen.</p>
</li>
</ol>
<p>For the purpose of this article, we will focus on the built-in <strong>Imperative Navigation</strong> and the more scalable <strong>Named Routes</strong>, illustrating them with the Car List App example. Let’s see how they work.</p>
<h2 id="heading-the-simple-navigator-api-navigatorpush">The Simple Navigator API: <code>Navigator.push</code></h2>
<p>The most straightforward way to navigate in Flutter is using <code>Navigator.push</code>. This method takes a <code>MaterialPageRoute</code> (or a <code>CupertinoPageRoute</code> for iOS-style transitions) that defines the widget for the new screen.</p>
<pre><code class="lang-dart">Navigator.push(
  context,
  MaterialPageRoute(builder: (context) =&gt; DetailsScreen()),
);
</code></pre>
<p><strong>Characteristics:</strong></p>
<ul>
<li><p><strong>Best for smaller apps:</strong> Where the number of screens is limited and data passing is simple.</p>
</li>
<li><p><strong>Can pass data using constructor:</strong> You can directly pass data to the new screen's constructor (for example, <code>DetailsScreen(car: myCar)</code>). This is intuitive for simple data.</p>
</li>
</ul>
<p>While easy to use, <code>Navigator.push</code> can become cumbersome for larger apps as it requires direct instantiation of widgets at every navigation point, making centralized route management difficult.</p>
<h2 id="heading-named-routes-the-scalable-approach">Named Routes: The Scalable Approach</h2>
<p>For applications with multiple screens and a more defined navigation structure, <strong>named routes</strong> offer a cleaner and more scalable solution. With named routes, you define a map of string names to screen-building functions within your <code>MaterialApp</code>.</p>
<p>Our Car List App perfectly demonstrates this:</p>
<pre><code class="lang-dart"><span class="hljs-comment">// In MyApp widget's build method</span>
MaterialApp(
  initialRoute: <span class="hljs-string">'/'</span>, <span class="hljs-comment">// The starting screen of our app</span>
  routes: {
    <span class="hljs-string">'/'</span>: (context) =&gt; HomeScreen(),          <span class="hljs-comment">// Maps '/' to HomeScreen</span>
    <span class="hljs-string">'/details'</span>: (context) =&gt; DetailsScreen(), <span class="hljs-comment">// Maps '/details' to DetailsScreen</span>
    <span class="hljs-string">'/profile'</span>: (context) =&gt; ProfileScreen(), <span class="hljs-comment">// Maps '/profile' to ProfileScreen</span>
  },
);
</code></pre>
<p>To navigate using a named route, you use <code>Navigator.pushNamed()</code>:</p>
<pre><code class="lang-dart"><span class="hljs-comment">// From HomeScreen to DetailsScreen</span>
Navigator.pushNamed(context, <span class="hljs-string">'/details'</span>);

<span class="hljs-comment">// From HomeScreen to ProfileScreen</span>
Navigator.pushNamed(context, <span class="hljs-string">'/profile'</span>);
</code></pre>
<p><strong>Advantages of named routes:</strong></p>
<ul>
<li><p><strong>More scalable:</strong> As your app grows, managing routes by name is far easier than scattering <code>MaterialPageRoute</code> instantiations throughout your codebase.</p>
</li>
<li><p><strong>Easy to centralize route management:</strong> All your app's main navigation paths are defined in one clear location (the <code>routes</code> map).</p>
</li>
<li><p><strong>Improved readability:</strong> Route names provide semantic meaning to your navigation actions.</p>
</li>
</ul>
<h3 id="heading-passing-and-receiving-data-with-named-routes">Passing and Receiving Data with Named Routes</h3>
<p>A common requirement for multi-screen apps is passing data from one screen to the next (for example, a selected car object from the list to its detail view). With named routes, the <code>arguments</code> property of <code>Navigator.pushNamed</code> is the idiomatic way to do this.</p>
<p>When navigating:</p>
<pre><code class="lang-dart"><span class="hljs-comment">// From HomeScreen, passing the 'car' object to the DetailsScreen</span>
Navigator.pushNamed(context, <span class="hljs-string">'/details'</span>, arguments: car);
</code></pre>
<p>On the receiving screen, <code>ModalRoute.of(context)!.settings.arguments</code> is used to retrieve the passed data. Remember to cast it to the expected type and handle nullability.</p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DetailsScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-comment">// Retrieve the Car object passed as arguments</span>
    <span class="hljs-keyword">final</span> Car car = ModalRoute.of(context)!.settings.arguments <span class="hljs-keyword">as</span> Car;

    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(title: Text(car.name)),
      <span class="hljs-comment">// ... rest of the UI using 'car' data</span>
    );
  }
}
</code></pre>
<p>This pattern ensures type safety (with the <code>as Car</code> cast) and allows any data type to be passed, from simple strings to complex custom objects.</p>
<h2 id="heading-backstack-management-controlling-user-flow">Backstack Management: Controlling User Flow</h2>
<p>The <code>Navigator</code> manages a <strong>stack of routes</strong>. When you <code>push</code> a new route, it's added to the top. When you go back, the top route is <code>popped</code> off the stack. Understanding and controlling this backstack is crucial for a smooth user experience.</p>
<ul>
<li><p><code>Navigator.pop(context)</code>: This is the most common way to return to the previous screen. It removes the topmost route from the navigation stack. In our app, both <code>DetailsScreen</code> and <code>ProfileScreen</code> use this to return to <code>HomeScreen</code>.</p>
<pre><code class="lang-dart">  <span class="hljs-comment">// In DetailsScreen or ProfileScreen</span>
  ElevatedButton.icon(
    onPressed: () =&gt; Navigator.pop(context), <span class="hljs-comment">// Go back to the previous screen</span>
    icon: Icon(Icons.arrow_back),
    label: Text(<span class="hljs-string">'Back'</span>),
  )
</code></pre>
</li>
<li><p><code>Navigator.pushReplacementNamed(context, '/newRouteName')</code>: Use this if you don't want the user to go back to the <em>current</em> screen. It replaces the current route on the stack with the new one. This is ideal for scenarios like a login screen, where after successful login, you don't want the user to be able to go back to the login page using the back button.</p>
</li>
<li><p><code>Navigator.pushNamedAndRemoveUntil(context, '/newRouteName', (route) =&gt; false)</code>: This powerful method pushes a new route and then removes <em>all</em> the previous routes until the <code>predicate</code> function returns <code>true</code>. If the predicate always returns <code>false</code> (as shown), it clears the entire stack and makes the new route the only one. This is perfect for <strong>login flows, onboarding, or splash screens</strong> where, once completed, the user should not be able to return to those initial screens.</p>
</li>
</ul>
<h2 id="heading-code-organization-tips-for-scalable-navigation">Code Organization Tips for Scalable Navigation</h2>
<p>As your app grows, maintaining a clear structure for your multi-screen components becomes vital. Here are some tips to help you keep things organized.</p>
<p><strong>1. Organize by feature:</strong> Instead of dumping all screens into one folder, group files related to a specific feature. For example:</p>
<ul>
<li><p><code>lib/features/home/home_screen.dart</code></p>
</li>
<li><p><code>lib/features/home/widgets/</code></p>
</li>
<li><p><code>lib/features/details/details_screen.dart</code></p>
</li>
<li><p><code>lib/features/profile/profile_screen.dart</code></p>
</li>
</ul>
<p><strong>2. Use dedicated folders for UI components:</strong></p>
<ul>
<li><p><code>lib/widgets/</code> (for reusable UI widgets across features)</p>
</li>
<li><p><code>lib/screens/</code> (for top-level screen widgets, or within feature folders)</p>
</li>
</ul>
<p><strong>3. Abstract navigation logic:</strong> For bigger apps, consider creating a separate file (for example, <code>lib/utils/app_routes.dart</code>) to hold all your named route constants and potentially even methods for simplified navigation, rather than hardcoding string literals.</p>
<h2 id="heading-scalable-navigation-when-built-in-isnt-enough">Scalable Navigation: When Built-in Isn't Enough</h2>
<p>While named routes are excellent for many applications, very large or complex apps with deep nested navigation, dynamic route generation, or specific web-based routing needs might benefit from third-party packages that offer a <strong>declarative navigation</strong> approach.</p>
<p>Consider packages like:</p>
<ul>
<li><p><code>go_router</code>: A Google-supported package that focuses on declarative routing, deep linking, and web-friendly URLs. It maps application state to URLs, providing a powerful and flexible system.</p>
</li>
<li><p><code>auto_route</code>: This package uses code generation to automatically create routing boilerplate, reducing manual effort and potential errors for complex navigation graphs.</p>
</li>
</ul>
<p>These solutions provide higher-level abstractions and solve common headaches associated with scaling navigation in large applications.</p>
<h3 id="heading-understanding-the-car-list-app-example">Understanding the Car List App Example</h3>
<p>In this tutorial, we will be building a simple Car List App to illustrate the different navigation methods. This application will consist of these primary screens:</p>
<ol>
<li><p><strong>Car List Screen:</strong> This screen will display a list of cars, each with basic information like its name and year. Users will be able to tap on a car in this list.</p>
</li>
<li><p><strong>Car Detail Screen:</strong> When a user taps on a car from the list, they will be navigated to this screen, which will display more detailed information about the selected car.</p>
</li>
<li><p><strong>Profile Screen:</strong> When a user taps on the floating action button with the person icon, they will be navigated to the profile screen</p>
</li>
</ol>
<p>This straightforward example will allow us to clearly demonstrate how to navigate between screens, pass data from one screen to another, and manage the navigation stack using Flutter's built-in navigation systems.</p>
<p>Now let’s get into our Car List App project so you can really see how this all works.</p>
<h2 id="heading-how-to-set-up-your-flutter-project-the-car-list-app">How to Set Up Your Flutter Project: The Car List App</h2>
<p>To create this project, you'll first need Flutter installed and configured on your system. If you haven't already, ensure you have the Flutter SDK and a suitable IDE (like VS Code or Android Studio) set up.</p>
<h3 id="heading-step-1-create-a-new-flutter-project">Step 1: Create a New Flutter Project</h3>
<p>Open your terminal or command prompt and run the following command to create a new Flutter project:</p>
<pre><code class="lang-bash">flutter create car_list_app
</code></pre>
<p>This command creates a new directory named <code>car_list_app</code> with a basic Flutter project structure inside it.</p>
<h3 id="heading-step-2-organize-the-project-structure">Step 2: Organize the Project Structure</h3>
<p>Navigate into your new <code>car_list_app</code> directory (<code>cd car_list_app</code>). Inside the <code>lib</code> folder, you'll initially find <code>main.dart</code>. We're going to enhance this structure to better organize our code.</p>
<p>Here's the recommended directory structure for your project:</p>
<pre><code class="lang-dart">car_list_app/
├── lib/
│   ├── main.dart
│   ├── models/
│   │   └── car.dart
│   ├── data/
│   │   └── dummy_data.dart
│   ├── screens/
│   │   ├── home_screen.dart
│   │   ├── details_screen.dart
│   │   └── profile_screen.dart
│   └── widgets/
│       └── car_list_tile.dart (Optional, <span class="hljs-keyword">for</span> more complex list items)
├── pubspec.yaml
├── ... (other Flutter project files)
</code></pre>
<p>Now, let's populate these files with your provided code.</p>
<h3 id="heading-step-3-populate-the-files">Step 3: Populate the Files</h3>
<h4 id="heading-1-libmodelscardart">1. <code>lib/models/car.dart</code></h4>
<p>This file will contain your <code>Car</code> data model.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// lib/models/car.dart</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> id;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> name;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> imageUrl;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> description;

  Car({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.id,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.name,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.imageUrl,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.description,
  });
}
</code></pre>
<h4 id="heading-2-libdatadummydatadart">2. <code>lib/data/dummy_data.dart</code></h4>
<p>This file will hold your static car data list. In a real application, this data would likely come from an API or database.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// lib/data/dummy_data.dart</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'../models/car.dart'</span>;

<span class="hljs-keyword">final</span> <span class="hljs-built_in">List</span>&lt;Car&gt; carList = [
  Car(
    id: <span class="hljs-string">'1'</span>,
    name: <span class="hljs-string">'Tesla Model S'</span>,
    imageUrl: <span class="hljs-string">'https://hips.hearstapps.com/hmg-prod/images/2025-tesla-model-s-2-672d42e16475f.jpg?crop=0.503xw:0.502xh;0.262xw,0.289xh&amp;resize=980:*'</span>,
    description: <span class="hljs-string">'Electric car with autopilot features.'</span>,
  ),
  Car(
    id: <span class="hljs-string">'2'</span>,
    name: <span class="hljs-string">'BMW M4'</span>,
    imageUrl: <span class="hljs-string">'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/2021_BMW_M4_Competition_Automatic_3.0_Front.jpg/1200px-2021_BMW_M4_Competition_Automatic_3.0_Front.jpg'</span>,
    description: <span class="hljs-string">'Sporty and powerful coupe.'</span>,
  ),
  Car(
    id: <span class="hljs-string">'3'</span>,
    name: <span class="hljs-string">'Ford Mustang'</span>,
    imageUrl: <span class="hljs-string">'https://images.prismic.io/carwow/c2d2e740-99e2-4faf-8cfa-b5a75c5037c0_ford-mustang-2024-lhd-front34static.jpg?auto=format&amp;cs=tinysrgb&amp;fit=max&amp;q=60'</span>,
    description: <span class="hljs-string">'Iconic American muscle car.'</span>,
  ),
];
</code></pre>
<h4 id="heading-3-libscreenshomescreendart">3. <code>lib/screens/home_screen.dart</code></h4>
<p>This file will contain the <code>HomeScreen</code> widget. Notice that the imports now point to our new file locations.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// lib/screens/home_screen.dart</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'../data/dummy_data.dart'</span>; <span class="hljs-comment">// Import dummy data</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'../models/car.dart'</span>;    <span class="hljs-comment">// Import Car model</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Available Cars'</span>)),
      body: ListView.builder(
        itemCount: carList.length,
        itemBuilder: (context, index) {
          <span class="hljs-keyword">final</span> car = carList[index];
          <span class="hljs-keyword">return</span> Card(
            margin: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">8</span>),
            child: ListTile(
              contentPadding: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">10</span>),
              leading: CircleAvatar(
                radius: <span class="hljs-number">40</span>,
                backgroundImage: NetworkImage(car.imageUrl),
              ),
              title: Text(car.name, style: <span class="hljs-keyword">const</span> TextStyle(fontWeight: FontWeight.bold)),
              subtitle: Text(car.description, maxLines: <span class="hljs-number">2</span>, overflow: TextOverflow.ellipsis),
              onTap: () {
                Navigator.pushNamed(
                  context,
                  <span class="hljs-string">'/details'</span>,
                  arguments: car,
                );
              },
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () =&gt; Navigator.pushNamed(context, <span class="hljs-string">'/profile'</span>),
        child: <span class="hljs-keyword">const</span> Icon(Icons.person),
        tooltip: <span class="hljs-string">'Go to Profile'</span>,
      ),
    );
  }
}
</code></pre>
<h4 id="heading-4-libscreensdetailsscreendart">4. <code>lib/screens/details_screen.dart</code></h4>
<p>This file will hold the <code>DetailsScreen</code> widget.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// lib/screens/details_screen.dart</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'../models/car.dart'</span>; <span class="hljs-comment">// Import Car model</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DetailsScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">final</span> Car car = ModalRoute.of(context)!.settings.arguments <span class="hljs-keyword">as</span> Car;

    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(title: Text(car.name)),
      body: Center(
        child: SingleChildScrollView(
          padding: <span class="hljs-keyword">const</span> EdgeInsets.all(<span class="hljs-number">16.0</span>),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ClipRRect(
                borderRadius: BorderRadius.circular(<span class="hljs-number">20</span>),
                child: Image.network(
                  car.imageUrl,
                  width: <span class="hljs-number">250</span>,
                  height: <span class="hljs-number">250</span>,
                  fit: BoxFit.cover,
                ),
              ),
              <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">24</span>),
              Text(
                car.name,
                style: <span class="hljs-keyword">const</span> TextStyle(fontSize: <span class="hljs-number">26</span>, fontWeight: FontWeight.bold),
                textAlign: TextAlign.center,
              ),
              <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">12</span>),
              Text(
                car.description,
                style: <span class="hljs-keyword">const</span> TextStyle(fontSize: <span class="hljs-number">16</span>),
                textAlign: TextAlign.center,
              ),
              <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">40</span>),
              ElevatedButton.icon(
                onPressed: () =&gt; Navigator.pop(context),
                icon: <span class="hljs-keyword">const</span> Icon(Icons.arrow_back),
                label: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Back'</span>),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
</code></pre>
<h4 id="heading-5-libscreensprofilescreendart">5. <code>lib/screens/profile_screen.dart</code></h4>
<p>This file will contain the <code>ProfileScreen</code> widget.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// lib/screens/profile_screen.dart</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProfileScreen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> profileImage = <span class="hljs-string">'https://www.shutterstock.com/image-vector/young-smiling-man-avatar-brown-600nw-2261401207.jpg'</span>;

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(title: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'My Profile'</span>)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center, <span class="hljs-comment">// Center content vertically</span>
          children: [
            CircleAvatar(
              radius: <span class="hljs-number">60</span>,
              backgroundImage: NetworkImage(profileImage),
            ),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">20</span>),
            <span class="hljs-keyword">const</span> Text(
              <span class="hljs-string">'John Doe'</span>,
              style: TextStyle(fontSize: <span class="hljs-number">22</span>, fontWeight: FontWeight.bold),
            ),
            Text(<span class="hljs-string">'john.doe@example.com'</span>, style: TextStyle(color: Colors.grey[<span class="hljs-number">600</span>])),
            <span class="hljs-keyword">const</span> SizedBox(height: <span class="hljs-number">30</span>),
            ElevatedButton.icon(
              onPressed: () =&gt; Navigator.pop(context),
              icon: <span class="hljs-keyword">const</span> Icon(Icons.arrow_back),
              label: <span class="hljs-keyword">const</span> Text(<span class="hljs-string">'Back to Home'</span>),
            ),
          ],
        ),
      ),
    );
  }
}
</code></pre>
<h4 id="heading-6-libmaindart">6. <code>lib/main.dart</code></h4>
<p>Finally, your <code>main.dart</code> will become much cleaner, and will mainly be responsible for running the app and defining the global routes.</p>
<pre><code class="lang-dart"><span class="hljs-comment">// lib/main.dart</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'screens/home_screen.dart'</span>;    <span class="hljs-comment">// Import HomeScreen</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'screens/details_screen.dart'</span>; <span class="hljs-comment">// Import DetailsScreen</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'screens/profile_screen.dart'</span>; <span class="hljs-comment">// Import ProfileScreen</span>

<span class="hljs-keyword">void</span> main() =&gt; runApp(<span class="hljs-keyword">const</span> MyApp()); <span class="hljs-comment">// Add const for MyApp</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-keyword">const</span> MyApp({<span class="hljs-keyword">super</span>.key}); <span class="hljs-comment">// Add const constructor</span>

  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> MaterialApp(
      title: <span class="hljs-string">'Car List App'</span>,
      theme: ThemeData(primarySwatch: Colors.blue),
      initialRoute: <span class="hljs-string">'/'</span>,
      routes: {
        <span class="hljs-string">'/'</span>: (context) =&gt; <span class="hljs-keyword">const</span> HomeScreen(),      <span class="hljs-comment">// Add const to screen widgets</span>
        <span class="hljs-string">'/details'</span>: (context) =&gt; <span class="hljs-keyword">const</span> DetailsScreen(),
        <span class="hljs-string">'/profile'</span>: (context) =&gt; <span class="hljs-keyword">const</span> ProfileScreen(),
      },
    );
  }
}
</code></pre>
<h3 id="heading-step-4-run-your-application">Step 4: Run Your Application</h3>
<p>After structuring your project and placing the code in the respective files, you can run your application from the root of your <code>car_list_app</code> directory:</p>
<pre><code class="lang-bash">flutter run
</code></pre>
<p>This will launch the app on your connected device or emulator. You should see the list of cars, and be able to navigate to their details and the profile screen, demonstrating the clean multi-screen architecture and routing you've implemented.</p>
<h3 id="heading-screenshots">Screenshots</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749887050970/68969384-f510-4a77-b08f-989440f9a7ac.png" alt="home screen screenshot" class="image--center mx-auto" width="3558" height="2120" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749887061102/a293159f-77b9-4904-8a86-d98ba73cf574.png" alt="detail screen screenshot" class="image--center mx-auto" width="3558" height="2120" loading="lazy"></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749887072401/452170e1-770c-4807-a648-941c397f84ec.png" alt="profile screen screenshot" class="image--center mx-auto" width="3558" height="2120" loading="lazy"></p>
<p>You can view the completed project here: <a target="_blank" href="https://github.com/Atuoha/routing_workshop">https://github.com/Atuoha/routing_workshop</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This organized structure significantly improves readability, reusability, and maintainability as your Flutter applications grow in complexity.</p>
<p>Building effective multi-screen applications in Flutter hinges on a clear understanding and strategic implementation of its navigation systems. From the simplicity of <code>Navigator.push</code> to the scalability of named routes with <code>Navigator.pushNamed</code> and <code>ModalRoute.of</code>, Flutter offers robust tools for managing your app's flow and passing essential data between screens.</p>
<p>By thoughtfully organizing your code and leveraging the appropriate navigation strategy, you can create user-friendly, maintainable, and scalable Flutter applications that stand out in the crowded app marketplace.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ React Navigation – How to Build a Breadcrumb Component ]]>
                </title>
                <description>
                    <![CDATA[ I know what you're thinking – but despite the article title and cover image, this article isn't about bread or even pastries. Instead, it looks at a commonly used component in web applications for navigation called the breadcrumb component. Here, we'... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-navigation-build-a-breadcrumb-component/</link>
                <guid isPermaLink="false">66bb8914b0d3ac3d7acde3dd</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-navigation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tailwind ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Mon, 25 Mar 2024 22:33:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/Breadcrumb-article-cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I know what you're thinking – but despite the article title and cover image, this article isn't about bread or even pastries. Instead, it looks at a commonly used component in web applications for navigation called the breadcrumb component.</p>
<p>Here, we'll unravel the mysteries of breadcrumb trails in React applications. We'll dissect their types, and you'll learn how to seamlessly integrate them into your web projects for better user navigation.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Fundamentals of CSS and TailwindCSS</li>
<li>Fundamentals of ES6 JavaScript and React </li>
<li>Fundamentals of Routing and the React Router library ( check out this <a target="_blank" href="https://www.freecodecamp.org/news/improve-user-experience-in-react-by-animating-routes-using-framer-motion/">routing article</a> if you’re unfamiliar).</li>
</ul>
<h2 id="heading-what-well-cover">What We'll Cover:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-understanding-breadcrumbs">Understanding Breadcrumbs</a></li>
<li><a class="post-section-overview" href="#heading-types-of-breadcrumb-navigation">Types of Breadcrumb Navigation</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-breadcrumb-component-in-react">How to Build the Breadcrumb Component in React</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-breadcrumb-component-structure">How to Create the Breadcrumb Component Structure</a><br>– <a class="post-section-overview" href="#heading-location-based-breadcrumbs">Location-Based Breadcrumbs</a><br>– <a class="post-section-overview" href="#heading-path-based-breadcrumbs">Path-Based Breadcrumbs</a><br>– <a class="post-section-overview" href="#heading-attribute-based-breadcrumbs">Attribute-Based Breadcrumbs</a></li>
<li><a class="post-section-overview" href="#heading-best-practices-for-breadcrumbs-in-react">Best Practices for Breadcrumbs in React</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-understanding-breadcrumbs">Understanding Breadcrumbs</h2>
<p>Before we venture deeper into the intricacies of breadcrumbs, let's set the scene. Imagine the classic tale of <a target="_blank" href="https://en.wikipedia.org/wiki/Hansel_and_Gretel">Hansel and Gretel</a>, where they leave a trail of breadcrumbs to find their way back home through the dense forest. </p>
<p>In the digital realm, breadcrumbs serve a similar purpose, albeit with a twist.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Hansel-And-Gretel-2.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Hansel And Gretel</em></p>
<p>Breadcrumbs, in the context of web navigation, are a series of hierarchical links typically displayed at the top of a webpage. These links reflect the user's path from the homepage to the current page, allowing them to retrace their steps or navigate to higher-level pages.</p>
<p>These navigation aids have a fascinating history and a crucial role in guiding users through a digital space.</p>
<p>A typical example of what this component looks like is shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Breadcrumb-example.png" alt="Image" width="600" height="400" loading="lazy">
<em>Breadcrumb example: Home Page &gt; Products Page &gt; Single Product Page (current page)</em></p>
<h3 id="heading-types-of-breadcrumb-navigation">Types of Breadcrumb Navigation</h3>
<ul>
<li><strong>Location-based Breadcrumbs</strong>: Like landmarks in a forest, location-based breadcrumbs show users where they are within the website's hierarchy. They show the current page's position relative to other pages on the site.</li>
<li><strong>Path-based Breadcrumbs</strong>: Like retracing your steps in the forest, path-based breadcrumbs display the user's journey through the website. They show the sequence of pages visited, helping users understand how they arrived at the current page.</li>
<li><strong>Attribute-based Breadcrumbs</strong>: These breadcrumbs highlight specific attributes or characteristics of the current page. They offer more context to the user's navigation, akin to discovering unique features along a trail.</li>
</ul>
<h2 id="heading-how-to-build-the-breadcrumb-component-in-react">How to Build the Breadcrumb Component in React</h2>
<p>The first step in this section involves creating a React environment. Before you begin, make sure to install <a target="_blank" href="https://nodejs.org/en/download">Node.js</a> on your computer if you don't have it already.</p>
<h3 id="heading-how-to-set-up-a-react-environment">How to Set Up a React Environment</h3>
<p>After installing Node.js, use <a target="_blank" href="https://vitejs.dev/guide/">Vite</a> (a modern build tool for React projects) to create a new React project. In your local terminal, run the command:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>Select React as your framework and your preferred variant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Setting-up-a-react-environment-with-Vite.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting up a react environment with Vite</em></p>
<p>To install the necessary packages, run <code>npm install</code> and open it in your IDE.</p>
<p>Finally, clear the boilerplate code and start up your server using the command <code>npm run dev</code>.</p>
<p>This project will use Tailwind for styling. To get that set up, run the following command:</p>
<pre><code class="lang-bash">npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
</code></pre>
<p>After this command, a <code>tailwind.config.js</code> file will be created. Head into the config file, delete its content, and paste this in there instead:</p>
<pre><code class="lang-js"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./index.html"</span>,
    <span class="hljs-string">"./src/**/*.{js,ts,jsx,tsx}"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [],
}
</code></pre>
<p>Then, open your <code>index.css</code> file and paste the style configs (preferably at the top):</p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> components;
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<p>Finally, restart your dev server to get access to Tailwind.</p>
<h2 id="heading-how-to-create-the-breadcrumb-component-structure">How to Create the Breadcrumb Component Structure</h2>
<p>Rather than building one breadcrumb component, we’re going to build all three types mentioned above so you can see how they work.</p>
<h3 id="heading-location-based-breadcrumbs">Location-Based Breadcrumbs</h3>
<p>This type is the most basic type of breadcrumb that involves showing all the routes readily available for the user to navigate.</p>
<p>To begin, start by creating a Breadcrumb file and pasting in these styles:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> SlashImg <span class="hljs-keyword">from</span> <span class="hljs-string">"./assets/slash.png"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Breadcrumb</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-white "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" flex border p-2 gap-6 text-xl text-[#2E4053] items-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md"</span>&gt;</span>
          Home
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md transition-all duration-300"</span>&gt;</span>
          Products
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md transition-all duration-300"</span>&gt;</span>
          About
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md transition-all duration-300"</span>&gt;</span>
          FAQ
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Then import this file into a <code>Home</code> component which you also need to create:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Breadcrumb <span class="hljs-keyword">from</span> <span class="hljs-string">"./Breadcrumb"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" h-[100dvh] bg-gray-200"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center gap-8 "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" text-4xl text-[#2E4053 ] mt-20"</span>&gt;</span>
          My Breadcrumb Component 🍞
        <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Breadcrumb</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>At the moment, your component looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Breadcrumb-after-rendering-on-UI.png" alt="Image" width="600" height="400" loading="lazy">
<em>Breadcrumb after rendering on UI</em></p>
<p>To perform navigation functionalities with this component, start by installing <a target="_blank" href="https://www.npmjs.com/package/react-router-dom">React Router</a> (a widely used library for managing navigation and routing in React applications).</p>
<pre><code class="lang-bash">npm i react-router-dom
</code></pre>
<p>Then create the routes in your App component.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { BrowserRouter, Navigate, Route, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> About <span class="hljs-keyword">from</span> <span class="hljs-string">"./About"</span>;
<span class="hljs-keyword">import</span> FAQ <span class="hljs-keyword">from</span> <span class="hljs-string">"./FAQ"</span>;
<span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">"./Home"</span>;
<span class="hljs-keyword">import</span> Homepage <span class="hljs-keyword">from</span> <span class="hljs-string">"./Homepage"</span>;
<span class="hljs-keyword">import</span> Products <span class="hljs-keyword">from</span> <span class="hljs-string">"./Products"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Navigate</span> <span class="hljs-attr">replace</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"home"</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span>}&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"home"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Homepage</span> /&gt;</span>} /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"products"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Products</span> /&gt;</span>} /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"about"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">About</span> /&gt;</span>} /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"faq"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">FAQ</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<p>The code block above is a configuration for client-side routing in a React application using React Router v6. It sets up a <code>BrowserRouter</code> to handle dynamic routing and defines a series of Route components within Routes to map URL paths to React components.</p>
<ul>
<li><code>BrowserRouter</code> is a router implementation that uses the HTML5 history API to keep the UI in sync with the URL.</li>
<li><code>Navigate</code> redirects users to a specific route. In this case, it redirects from the index route to <code>/home</code>.</li>
<li><code>Route</code> components define a mapping between a path and a component. The <code>element</code> prop specifies what to render when the path matches the current URL.</li>
<li>The <code>path="/" element={&lt;Home /&gt;}</code> route is a nested route that serves as a layout for its child routes. It renders the Home component when the URL is <code>/</code>. Nested inside the <code>Home</code> route are routes for <code>home</code>, <code>products</code>, <code>about</code>, and <code>faq</code>, each rendering their respective components when their path matches the URL.</li>
</ul>
<p>Next, head over to your Breadcrumb component and change the list elements to <code>Link</code> elements (imported from React Router) to aid routing between routes.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> SlashImg <span class="hljs-keyword">from</span> <span class="hljs-string">"./assets/slash.png"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Breadcrumb</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-white "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" flex border p-2 gap-6 text-xl text-[#2E4053] items-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">home</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md"</span>&gt;</span>
          Home
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">products</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md transition-all duration-300"</span>&gt;</span>
          Products
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">about</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md transition-all duration-300"</span>&gt;</span>
          About
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">faq</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">" cursor-pointer hover:bg-[#E8DAEF] p-4 rounded-md transition-all duration-300"</span>&gt;</span>
          FAQ
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Then use the <code>Outlet</code> component provided by React Router to display the content of each route in the <code>Home</code> component.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Breadcrumb <span class="hljs-keyword">from</span> <span class="hljs-string">"./Breadcrumb"</span>;
<span class="hljs-keyword">import</span> { Outlet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" h-[100dvh] bg-gray-200"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center gap-8 "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" text-4xl text-[#2E4053 ] mt-20"</span>&gt;</span>
          My Breadcrumb Component 🍞
        <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Breadcrumb</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Outlet</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Testing out your component in the browser now gives the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Routing-with-the-Breadcrumb-component.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Routing with the Breadcrumb component</em></p>
<p>With this, your location-based breadcrumbs are functional, but we can take it a step further. To improve the UX, we can add an active class to the currently active route, creating a visual indicator of where the user is at every point in time.</p>
<p>Start by extracting the current location of the user in the Breadcrumb component:</p>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> location = useLocation();
</code></pre>
<p>Then use the pathname property to add an active class to each link:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Link, useLocation } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> SlashImg <span class="hljs-keyword">from</span> <span class="hljs-string">"./assets/slash.png"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Breadcrumb</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> location = useLocation();
  <span class="hljs-built_in">console</span>.log(location.pathname);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-white "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" flex border p-2 gap-6 text-xl text-[#2E4053] items-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">home</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
            <span class="hljs-attr">location.pathname</span> === <span class="hljs-string">"/home"</span> &amp;&amp; "<span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
          }`}&gt;</span>
          Home
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">products</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
            <span class="hljs-attr">location.pathname</span> === <span class="hljs-string">"/products"</span> &amp;&amp; "<span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
          }`}&gt;</span>
          Products
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">about</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
            <span class="hljs-attr">location.pathname</span> === <span class="hljs-string">"/about"</span> &amp;&amp; "<span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
          }`}&gt;</span>
          About
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{SlashImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">faq</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
            <span class="hljs-attr">location.pathname</span> === <span class="hljs-string">"/faq"</span> &amp;&amp; "<span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
          }`}&gt;</span>
          FAQ
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This now gives the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Routing-with-the-Breadcrumb-component-after-adding-an-active-class.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Routing with the Breadcrumb component after adding an active class</em></p>
<p>Tasty! 🍩</p>
<h3 id="heading-path-based-breadcrumbs">Path-Based Breadcrumbs</h3>
<p>This breadcrumb type uses the pattern of progressive reveal to better guide the users on where they are based on their actions.</p>
<p>Here we’re going to create two routes and move from the first to the third (Home to Single product page).</p>
<p>Start by modifying your <code>Home</code> component a bit.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" h-[100dvh] bg-gray-200"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center gap-8 "</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" text-4xl text-[#2E4053 ] mt-20"</span>&gt;</span>
          My Breadcrumb Component 🍞
        <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Breadcrumb</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Outlet</span> /&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-4 p-2 "</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"products"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" rounded-md p-2 bg-[#777] text-white"</span>&gt;</span>
            Products
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
            <span class="hljs-attr">to</span>=<span class="hljs-string">"products/1"</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">" rounded-md p-2 bg-[#777] text-white"</span>&gt;</span>
            Single Product
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>The changes include creating a single product page which we'll route to later.</p>
<p>Then make a nested route path for the page in the App component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { BrowserRouter, Navigate, Route, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">"./Home"</span>;
<span class="hljs-keyword">import</span> Homepage <span class="hljs-keyword">from</span> <span class="hljs-string">"./Homepage"</span>;
<span class="hljs-keyword">import</span> Products <span class="hljs-keyword">from</span> <span class="hljs-string">"./Products"</span>;
<span class="hljs-keyword">import</span> SingleProduct <span class="hljs-keyword">from</span> <span class="hljs-string">"./SingleProduct"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Navigate</span> <span class="hljs-attr">replace</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"home"</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Home</span> /&gt;</span>}&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"home"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Homepage</span> /&gt;</span>} /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"products"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Products</span> /&gt;</span>}&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">":productId"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">SingleProduct</span> /&gt;</span>} /&gt;
          <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<p>For the already existing Products page, add these styles and changes:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Outlet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Products</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-[#EDBB99] p-2 w-96 h-96 flex flex-col items-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Products Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Outlet</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Page-after-creating-the-Single-Product-page-without-any-routing-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Page after creating the Single Product page without any routing</em></p>
<p>Finally, modify your breadcrumb component to display the routes when you route to them from the home page.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Link, useLocation } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> RightArrowImg <span class="hljs-keyword">from</span> <span class="hljs-string">"./assets/right-icon.png"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Breadcrumb</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> location = useLocation();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-white "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" flex border p-2 gap-6 text-xl text-[#2E4053] items-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
          <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">home</span>"}
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">hover:text-black</span> <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
            <span class="hljs-attr">location.pathname</span> === <span class="hljs-string">"/home"</span> &amp;&amp; "<span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
          }`}&gt;</span>
          Home
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        {location.pathname.includes("/products") &amp;&amp; (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{RightArrowImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
              <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">products</span>"}
              <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>` <span class="hljs-attr">hover:text-black</span> <span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
                <span class="hljs-attr">location.pathname.includes</span>("/<span class="hljs-attr">products</span>") &amp;&amp;
                " <span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
              } ${
                <span class="hljs-attr">location.pathname.includes</span>("/<span class="hljs-attr">products</span>/") &amp;&amp;
                " <span class="hljs-attr">bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">text-black</span>"
              }`}&gt;</span>
              Products
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span>
        )}
        {location.pathname.includes(`/products/`) &amp;&amp; (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{RightArrowImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
              <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">products</span>"}
              <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">hover:text-black</span>  <span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">hover:bg-</span>[#<span class="hljs-attr">E8DAEF</span>] <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> ${
                <span class="hljs-attr">location.pathname.includes</span>("/<span class="hljs-attr">products</span>") &amp;&amp;
                "<span class="hljs-attr">bg-</span>[#<span class="hljs-attr">b572d6</span>] <span class="hljs-attr">text-white</span>"
              }`}&gt;</span>
              Single Product
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span></span>
        )}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>In the code above, we’re displaying more breadcrumbs based on the route we’re in and applying styles to reflect the route changes.</p>
<p>Testing our component now gives the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Routing-with-the-Breadcrumb-component-after-adding-a-nested-route.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Routing with the Breadcrumb component after adding a nested route</em></p>
<p>Sweet! 🍬</p>
<h3 id="heading-attribute-based-breadcrumbs">Attribute-Based Breadcrumbs</h3>
<p>Attribute-based breadcrumbs focus on highlighting specific attributes or characteristics of the current page, such as tags, categories, or any other relevant metadata.</p>
<p>Instead of simply showing the user's path through the website hierarchy, they provide additional context that can aid in navigation and understanding. </p>
<p>A common use case for them is on E-commerce sites where you go through multiple items and filter through multiple product properties to find your desired product.</p>
<p>To begin, our app component is going to look drastically different with no routing done.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Products <span class="hljs-keyword">from</span> <span class="hljs-string">"./Products"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" h-[100dvh] bg-[#EDBB99]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Products</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Then add this JSX to your <code>Products</code> component:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Breadcrumb <span class="hljs-keyword">from</span> <span class="hljs-string">"./Breadcrumb"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Products</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> dogsArray = [
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"S"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"white"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/small-white-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Gigi"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">1</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"M"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"white"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/medium-white-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Tom"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">2</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"L"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"white"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/big-white-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Jake"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"S"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"black"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/small-black-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Hill"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">1</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"M"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"black"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/medium-black-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Jack"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">2</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"L"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"black"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/big-black-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Jones"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"S"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"brown"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/small-brown-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Herbert"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">1</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"M"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"brown"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/medium-brown-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Coco"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">2</span>,
    },
    {
      <span class="hljs-attr">size</span>: <span class="hljs-string">"L"</span>,
      <span class="hljs-attr">color</span>: <span class="hljs-string">"brown"</span>,
      <span class="hljs-attr">image</span>: <span class="hljs-string">"/big-brown-dog.jpg"</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">"Benny"</span>,
      <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
    },
  ];


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center p-2"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4"</span>&gt;</span>Adopt Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Breadcrumb</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative grid grid-cols-5 gap-6"</span>&gt;</span>
          {dogsArray.map((dog) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{dog.name}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" w-[225px] rounded-md overflow-hidden"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full "</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{dog.image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid items-center grid-cols-2 gap-2 mt-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center gap-2"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Name:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white bg-orange-900 border rounded-[4px] p-1.5 min-w-14"</span>&gt;</span>
                    {dog.name}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Size:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white min-w-14"</span>&gt;</span>{dog.size}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Color:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white capitalize min-w-14"</span>&gt;</span>
                    {dog.color}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Age:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white min-w-14"</span>&gt;</span>
                    {`${dog.age + " " + "year"}${dog.age &gt; 1 ? "s" : ""}`}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          ))}

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"absolute bottom-0 left-0 p-1 translate-y-[110%]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-2"</span>&gt;</span>Filter by<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center mb-4"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12"</span>&gt;</span>Size:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">bg-white</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  All
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">bg-white</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  S
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">bg-white</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  M
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">bg-white</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  L
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12"</span>&gt;</span>Color:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">bg-white</span>  <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  All
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">bg-white</span>  <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">min-w-14</span>`}&gt;</span>
                  White
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">bg-white</span> <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  Brown
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">p-2</span> <span class="hljs-attr">text-center</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">bg-white</span>  <span class="hljs-attr">min-w-14</span> `}&gt;</span>
                  Black
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This JSX uses dummy dog data to create a template and style it with tailwind.</p>
<p>At the moment, your app should look like this;</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Page-after-looping-over-the-dummy-dog-data.png" alt="Image" width="600" height="400" loading="lazy">
<em>Page after looping over the dummy dog data</em></p>
<p>To implement the attribute-based breadcrumbs, start by creating two states for the attributes you want to filter by:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [sizeFilter, setSizeFilter] = useState(<span class="hljs-literal">null</span>);
<span class="hljs-keyword">const</span> [colorFilter, setColorFilter] = useState(<span class="hljs-literal">null</span>);
</code></pre>
<p>Then create a function to filter based on the value passed in:</p>
<pre><code class="lang-jsx">  <span class="hljs-keyword">const</span> filteredDogs = dogsArray.filter(<span class="hljs-function">(<span class="hljs-params">dog</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (sizeFilter &amp;&amp; dog.size !== sizeFilter) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> (colorFilter &amp;&amp; dog.color !== colorFilter) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  });
</code></pre>
<p>After that, change the array you used used to create the JSX to the array returned from the function:</p>
<pre><code class="lang-jsx"> {filteredDogs.map(<span class="hljs-function">(<span class="hljs-params">dog</span>) =&gt;</span> (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{dog.name}</span>&gt;</span></span>
</code></pre>
<p>Finally, use the setter function to pass in the values you want to filter by:</p>
<pre><code class="lang-jsx">&lt;main&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative grid grid-cols-5 gap-6"</span>&gt;</span>
          {filteredDogs.map((dog) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{dog.name}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" w-[225px] rounded-md overflow-hidden"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full "</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{dog.image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid items-center grid-cols-2 gap-2 mt-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center gap-2"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Name:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white bg-orange-900 border rounded-[4px] p-1.5 min-w-14"</span>&gt;</span>
                    {dog.name}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Size:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white min-w-14"</span>&gt;</span>{dog.size}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Color:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white capitalize min-w-14"</span>&gt;</span>
                    {dog.color}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Age:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white min-w-14"</span>&gt;</span>
                    {`${dog.age + " " + "year"}${dog.age &gt; 1 ? "s" : ""}`}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          ))}

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"absolute bottom-0 left-0 p-1 translate-y-[110%]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-2"</span>&gt;</span>Filter by<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center mb-4"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12"</span>&gt;</span>Size:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Reset</span> <span class="hljs-attr">size</span> <span class="hljs-attr">state</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter(null)}
                  className={`p-2 text-center bg-white rounded-md min-w-14 `}&gt;
                  All
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Set</span> <span class="hljs-attr">filter</span> <span class="hljs-attr">to</span> <span class="hljs-attr">small</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter("S")}
                  className={`p-2 text-center bg-white rounded-md min-w-14 `}&gt;
                  S
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Set</span> <span class="hljs-attr">filter</span> <span class="hljs-attr">to</span> <span class="hljs-attr">medium</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter("M")}
                  className={`p-2 text-center bg-white rounded-md min-w-14 `}&gt;
                  M
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Set</span> <span class="hljs-attr">filter</span> <span class="hljs-attr">to</span> <span class="hljs-attr">large</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter("L")}
                  className={`p-2 text-center bg-white rounded-md min-w-14 `}&gt;
                  L
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12"</span>&gt;</span>Color:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Reset</span> <span class="hljs-attr">color</span> <span class="hljs-attr">state</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter(null)}
                  className={`p-2 text-center bg-white  rounded-md min-w-14 `}&gt;
                  All
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Set</span> <span class="hljs-attr">color</span> <span class="hljs-attr">to</span> <span class="hljs-attr">white</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter("white")}
                  className={`p-2 text-center bg-white  rounded-md min-w-14 `}&gt;
                  White
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Set</span> <span class="hljs-attr">color</span> <span class="hljs-attr">to</span> <span class="hljs-attr">brown</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter("brown")}
                  className={`p-2 text-center rounded-md bg-white min-w-14 `}&gt;
                  Brown
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  // <span class="hljs-attr">Set</span> <span class="hljs-attr">color</span> <span class="hljs-attr">to</span> <span class="hljs-attr">black</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter("black")}
                  className={`p-2 text-center rounded-md bg-white  min-w-14 `}&gt;
                  Black
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      &lt;/main&gt;
</code></pre>
<p>Testing your component now gives the following result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Filtering-by-properties.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Filtering by properties working</em></p>
<p>Exquisite!🍦</p>
<p>To add our breadcrumb functionality, pass in the filter props to the component like this:</p>
<pre><code class="lang-jsx">&lt;Breadcrumb sizeFilter={sizeFilter} colorFilter={colorFilter} /&gt;
</code></pre>
<p>Then use those props to render the headers:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> RightArrowImg <span class="hljs-keyword">from</span> <span class="hljs-string">"./assets/right-icon.png"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Breadcrumb</span>(<span class="hljs-params">{ sizeFilter, colorFilter }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-4 bg-gray-200 rounded-md "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"   flex items-center  text-xl text-[#2E4053] text-left"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> `}&gt;</span>All<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

        {sizeFilter &amp;&amp; (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{RightArrowImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">capitalize</span>`}&gt;</span>
              {sizeFilter}
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span>
        )}
        {colorFilter &amp;&amp; (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{RightArrowImg}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-5 h-5 "</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">cursor-pointer</span> <span class="hljs-attr">p-4</span> <span class="hljs-attr">rounded-md</span> <span class="hljs-attr">capitalize</span>`}&gt;</span>
              {colorFilter}
            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span></span>
        )}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>Before we see the final result, let’s add indicators of what filter props are currently active:</p>
<pre><code class="lang-jsx">&lt;main&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"relative grid grid-cols-5 gap-6"</span>&gt;</span>
          {filteredDogs.map((dog) =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{dog.name}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" w-[225px] rounded-md overflow-hidden"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full "</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{dog.image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid items-center grid-cols-2 gap-2 mt-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center gap-2"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Name:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white bg-orange-900 border rounded-[4px] p-1.5 min-w-14"</span>&gt;</span>
                    {dog.name}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Size:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white min-w-14"</span>&gt;</span>{dog.size}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Color:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white capitalize min-w-14"</span>&gt;</span>
                    {dog.color}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2 "</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Age:<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center text-white min-w-14"</span>&gt;</span>
                    {`${dog.age + " " + "year"}${dog.age &gt; 1 ? "s" : ""}`}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          ))}

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"absolute bottom-0 left-0 p-1 translate-y-[110%]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mb-2"</span>&gt;</span>Filter by<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center mb-4"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12"</span>&gt;</span>Size:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter(null)}
                  className={`p-2 text-center  rounded-md min-w-14 ${
                    // Dynamic background color add
                    sizeFilter === null
                      ? "bg-orange-900 text-white"
                      : "bg-white text-black "
                  }`}&gt;
                  All
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter("S")}
                  className={`p-2 text-center  rounded-md min-w-14 ${
                    // Dynamic background color add
                    sizeFilter === "S"
                      ? "bg-orange-900 text-white"
                      : "bg-white text-black "
                  }`}&gt;
                  S
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter("M")}
                  className={`p-2 text-center  rounded-md min-w-14 ${
                    // Dynamic background color add
                    sizeFilter === "M"
                      ? "bg-orange-900 text-white"
                      : "bg-white text-black "
                  }`}&gt;
                  M
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setSizeFilter("L")}
                  className={`p-2 text-center  rounded-md min-w-14 ${
                    // Dynamic background color add
                    sizeFilter === "L"
                      ? "bg-orange-900 text-white"
                      : "bg-white text-black "
                  }`}&gt;
                  L
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-12"</span>&gt;</span>Color:<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter(null)}
                  className={`p-2 text-center   rounded-md min-w-14 ${
                    // Dynamic background color add
                    colorFilter === null
                      ? "bg-orange-900 text-white"
                      : "bg-white text-black "
                  }`}&gt;
                  All
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter("white")}
                  className={`p-2 text-center   rounded-md min-w-14 ${
                    // Dynamic background color add
                    colorFilter === "white"
                      ? "bg-orange-900 text-white"
                      : "bg-white text-black "
                  }`}&gt;
                  White
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter("brown")}
                  className={`p-2 text-center rounded-md   min-w-14 ${
                    // Dynamic background color add
                    colorFilter === "brown"
                      ? "bg-orange-900 text-white"
                      : " bg-white text-black "
                  }`}&gt;
                  Brown
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setColorFilter("black")}
                  className={`p-2 text-center rounded-md    min-w-14 ${
                    // Dynamic background color add
                    colorFilter === "black"
                      ? "bg-orange-900 text-white"
                      : " bg-white text-black"
                  }`}&gt;
                  Black
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      &lt;/main&gt;
</code></pre>
<p>A final test on your component now gives this result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Filtering-by-properties-tested.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Filtering via properties and showing it in the breadcrumb</em></p>
<p>And voilà! Your component filters perfectly, and also shows a useful breadcrumb to help users know what properties they’ve filtered by.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/bruce-almighty-jim-carrey.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Bruce Almighty Jim Carrey beautiful gif</em></p>
<h2 id="heading-best-practices-for-breadcrumbs-in-react">Best Practices for Breadcrumbs in React</h2>
<p>When implementing breadcrumbs in React, it's crucial to follow certain best practices to ensure a seamless user experience. Here are some key points to consider:</p>
<ol>
<li><strong>Consistency with React Routing</strong>: Breadcrumbs should align with the application's routing structure. You can do this by implementing dynamic breadcrumbs using a good routing library (React Router). By defining routes and generating an array of breadcrumbs based on the user's current route, you can ensure that the breadcrumb trail reflects the user's navigation path.</li>
<li><strong>Breadth and Depth of Breadcrumb Trails</strong>: Breadcrumb trails should represent the user's location within the application. This includes using a separator, such as a slash ("/"), to distinguish between different parts of the breadcrumb trail.</li>
<li><strong>Naming and Navigation</strong>: Breadcrumbs should be easy to understand and navigate. This involves using clear and descriptive names for each breadcrumb and ensuring that each breadcrumb link is clickable, leading the user to the appropriate page.</li>
<li><strong>Ensuring Accessibility</strong>: Breadcrumbs should be accessible to all users. This can be achieved by using the <code>aria-label</code> attribute to identify the breadcrumb trail as a navigation landmark. This makes it easier for users with assistive technologies to locate and navigate the breadcrumb trail.</li>
<li><strong>Customization and Ease-of-Use</strong>: When using a component for creating breadcrumbs, consider its customization options and ease of use. Look for components that provide useful defaults and allow for easy customization of texts, links, and separators.</li>
</ol>
<p>By adhering to these best practices, you can create effective and user-friendly breadcrumbs in your React applications. </p>
<p>Here are links to the repositories on GitHub:</p>
<ul>
<li><a target="_blank" href="https://github.com/Daiveedjay/React-breadcrumb-article-location-based">Location-based</a></li>
<li><a target="_blank" href="https://github.com/Daiveedjay/React-breadcrumb-article-path-based">Path-based</a></li>
<li><a target="_blank" href="https://github.com/Daiveedjay/React-breadcrumb-article-attribute-based">Attribute-based</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Implementing breadcrumbs in React applications not only provides a navigational aid but also contributes to a seamless and intuitive user experience. Adhering to best practices enhances the usability and accessibility of applications.</p>
<p>Just as the aroma of freshly baked bread entices hungry people to come visit the bakery, a well-structured breadcrumb trail can entice users to explore and navigate an application with ease, ultimately improving user navigation and experience. And that's how the cookie crumbles, leaving a trail of delightful navigation in its wake.</p>
<h3 id="heading-contact-information">Contact Information</h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter / X: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: Jajadavidjid@gmail.com  </li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use URLs for State Management in React ]]>
                </title>
                <description>
                    <![CDATA[ For years, URLs have been synonymous with web navigation. But the tide is turning, especially with the emergence of single-page applications. In the React universe, URLs are stepping up to play a pivotal role in state management. This article will gu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-urls-for-state-management-in-react/</link>
                <guid isPermaLink="false">66bb890b7a6500a14ba5b769</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ State Management  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ url ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Fri, 06 Oct 2023 17:50:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/Article-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For years, URLs have been synonymous with web navigation. But the tide is turning, especially with the emergence of single-page applications. In the React universe, URLs are stepping up to play a pivotal role in state management.</p>
<p>This article will guide you through the transformative journey of URLs as state managers in the context of React applications. </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Fundamentals of HTML and CSS</li>
<li>Fundamentals of ES6 JavaScript</li>
<li>Fundamentals of React, React Router and React Hooks.</li>
</ul>
<h2 id="heading-the-evolution-of-state-management-in-react">The Evolution of State Management in React</h2>
<p>Let's journey through the past:</p>
<ul>
<li><strong>setState</strong>: In the early days of React, many relied on component state, especially within <a target="_blank" href="https://react.dev/reference/react/Component#defining-a-class-component">class components</a>. It was straightforward to manage component-specific data. But it wasn't ideal for larger applications.</li>
<li><strong>Redux &amp; MobX</strong>: As applications grew in complexity, tools like <a target="_blank" href="https://redux.js.org/">Redux</a> and <a target="_blank" href="https://mobx.js.org/README.html">MobX</a> emerged. They centralized data management, making it easier to handle app-wide data.</li>
<li><strong>Context API &amp; Hooks</strong>: React's own <a target="_blank" href="https://react.dev/reference/react/useContext">Context API</a>, combined with the advent of hooks, brought about a more native way to manage the global state without adding extra libraries.</li>
</ul>
<h2 id="heading-managing-state-with-urls">Managing State with URLs</h2>
<p>At first, using a URL for managing state might seem unusual. But as you explore further, you'll discover several clear benefits:</p>
<ul>
<li><strong>Save Your Spot</strong>: By keeping state in the URL, your webpage remembers your place. So, if you bookmark a page, it will look the same when you come back to it later.</li>
<li><strong>Easy Sharing</strong>: If you're looking at something specific on a page, like a product or a chart, you can share the URL. Anyone who clicks it will see exactly what you’re seeing, making collaboration a breeze.</li>
<li><strong>Troubleshoot with Ease</strong>: Developers can find and fix issues faster because the URL shows the state of the app. They can see problems just by clicking on the shared link.</li>
</ul>
<p>In short, using URLs in this way helps keep your spot, share specific views, and makes problem-solving smoother for developers.</p>
<h2 id="heading-how-to-implement-url-based-state-management">How to Implement URL-based State Management</h2>
<p>Considering the size of this section, here’s everything you’ll learn.</p>
<ol>
<li>How to Set Up the Environment</li>
<li>Clearing the clutter</li>
<li>Project Breakdown / Analysis</li>
<li>Install the Necessary Dependencies</li>
<li>How to Fetch the Data and Design the UI</li>
<li>How to Store State in the URL</li>
<li>How to Read the State Stored in the URL</li>
<li>How to Customize the Product Page</li>
</ol>
<h3 id="heading-how-to-set-up-the-environment">How to Set Up the Environment</h3>
<p>Open your inbuilt terminal or code editor’s terminal (preferably) and run the following:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>This command uses <a target="_blank" href="https://vitejs.dev/guide/">Vite</a> (a lightweight tool that is used for building fast and optimized web applications) to scaffold a web app environment. Navigate down using your arrow keys and select React.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/02-Selecting-React.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting React from Vite Setup</em></p>
<p>Then select your preferred language combination – I’ll be using plain JS.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/03-Selecting-JS.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting Language in React</em></p>
<p>Next, move into your react folder using the cd “project-name” folder and run <code>npm install</code> to install all the project’s dependencies.</p>
<p>Finally, start the development server by running <code>npm run dev</code> and going to the respective URL (<a target="_blank" href="http://localhost:5173/">http://localhost:5173/</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/04-dev-server-running.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dev Server running</em></p>
<h3 id="heading-clearing-the-clutter">Clearing the clutter</h3>
<p>Make sure to clear the contents of all the CSS files and delete the <code>App.css</code> as you’ll need only 1 style file. Then, clear the contents of the <code>App</code> component and replace it with basic JSX content.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/05-clutter-cleared.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clutter Cleared in Dev Environment</em></p>
<p>This returns a clear page on your local server that looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/06-clear-server-page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clear Server page</em></p>
<h3 id="heading-project-breakdown-analysis">Project breakdown / analysis</h3>
<p>The project involves getting data from an API and persisting that data globally via the URL to be accessible across many components/pages.</p>
<p>A relatable example is when you’re on your favourite e-commerce site, you may see this cool gadget and want to share it with your friend.</p>
<p>You usually share the link from the browser to your friend’s social media DM which they can use to view the same product without any fuss by opening the link you sent to them.</p>
<p>Here’s a sneaky peek at the project we're going to build: 😉</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/1-sneaky-peek.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Sneaky peek of complete project</em></p>
<p>Intrigued?🌚 Let’s dive in then.</p>
<h3 id="heading-install-the-necessary-dependencies">Install the necessary dependencies</h3>
<p>Before you put anything on the page, you must first fully configure your development environment with the necessary dependencies.</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/json-server">json-server</a>: This package hosts your data on a local server, enabling you to fetch it like an external API.</li>
<li><a target="_blank" href="https://www.npmjs.com/package/react-router">react-router</a>: This package enables React to create SPAs that allow navigating without refreshing the page.</li>
</ul>
<pre><code class="lang-bash">npm i json-server react-router-dom
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/08-installing-dependencies-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Installing dependencies</em></p>
<ul>
<li>Then download the JSON data from this <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management/tree/main/data">GitHub(json-data)</a>, and the assets from this <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management/tree/main/public/assets">GitHub(assets-data)</a>.</li>
</ul>
<p>Now create a data folder in your root project directory and place the JSON file inside. Then create an assets folder in your public directory and place all images in that assets folder.</p>
<p>Your current folder structure should be like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/07-folder-structure-after-downloading-files.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder structure after downloading files</em></p>
<p>Next, modify your package.json file by adding a script which starts up the json-server</p>
<pre><code class="lang-json"><span class="hljs-string">"server"</span>: <span class="hljs-string">"json-server --watch data/products.json --port 9000 "</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/09-adding-a-server-script.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding server script to package.json</em></p>
<p>After that, open your terminal and start up the server with <code>npm run server</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/10-starting-data-server.png" alt="Image" width="600" height="400" loading="lazy">
<em>Starting data server</em></p>
<p>With this, your server is running and the content of your JSON file can be accessed through the URL provided.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/11-data-on-browser.png" alt="Image" width="600" height="400" loading="lazy">
<em>Data on Browser</em></p>
<p>Ps: If you want to view JSON files in the browser like I do, download the browser extension – <a target="_blank" href="https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh">JSON Viewer</a>.</p>
<h3 id="heading-how-to-fetch-the-data-and-design-the-ui">How to fetch the data and design the UI</h3>
<p>Start by creating a HomePage component and importing it into the App component. This component will contain all the data in the first screen you saw earlier.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/12-importing-the-homepage.png" alt="Image" width="600" height="400" loading="lazy">
<em>Importing the Homepage</em></p>
<p>In the <code>HomePage</code> component, use a <code>useEffect</code> hook to fetch all the data from your local API.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params"></span>) </span>{
  useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{

      <span class="hljs-keyword">try</span>{
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:9000/products"</span>);
      <span class="hljs-keyword">const</span> clothesData = <span class="hljs-keyword">await</span> res.json();
      <span class="hljs-built_in">console</span>.log(clothesData);   
      }
      <span class="hljs-keyword">catch</span> (error) {  <span class="hljs-built_in">console</span>.log(error);}
      }
    fetchData();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"homepage"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Homepage of my Dummy Product Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>At the moment, you can already view the data fetched in the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/13-evidence-of-fetching-data.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evidence of data fetching</em></p>
<p>Next, store your data in a state using the <code>useState</code> hook and populate your interface with that data.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [products, setProducts] = useState([]);

  useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:9000/products"</span>);
        <span class="hljs-keyword">const</span> clothesData = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-built_in">console</span>.log(clothesData);
        <span class="hljs-comment">//Storing happens here</span>
        setProducts(clothesData);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      }
    }
    fetchData();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"homepage"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Homepage of my Dummy Product Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"products__list"</span>&gt;</span>
        {products.map((product) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>
                      <span class="hljs-attr">className</span>=<span class="hljs-string">"product__item"</span>
          &gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{product.imageUrl}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{product.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>All the styling required in this project is in this <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management/blob/main/src/index.css">CSS file</a>. Alternatively, you can paste these stylings in your index.css, which gives the same result.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Nunito:wght@400;700&amp;display=swap"</span>);

*,
<span class="hljs-selector-pseudo">::before</span>,
<span class="hljs-selector-pseudo">::after</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}
<span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">62.5%</span>;
}
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Nunito"</span>, sans-serif;
}

<span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3rem</span>;

  &amp; span {
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">3rem</span>;
  }
}

<span class="hljs-selector-tag">a</span>,
<span class="hljs-selector-tag">h3</span> {
  <span class="hljs-attribute">text-decoration</span>: none;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#a04000</span>;
}

<span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">display</span>: block;
  <span class="hljs-attribute">transition</span>: all ease-in <span class="hljs-number">0.3s</span>;
}

<span class="hljs-selector-class">.homepage</span> {
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">3rem</span>;

  &amp; &gt; * {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  }
}

<span class="hljs-selector-class">.products__list</span> {
  <span class="hljs-attribute">column-count</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">column-gap</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;

  &amp; &gt; * {
    <span class="hljs-attribute">break-inside</span>: avoid;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">2rem</span>;
  }

  &amp; <span class="hljs-selector-class">.product__item</span> {
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">overflow</span>: hidden;
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">position</span>: relative;
    <span class="hljs-attribute">transition</span>: all ease-in <span class="hljs-number">0.3s</span>;

    &amp; h2 {
      <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;
      <span class="hljs-attribute">bottom</span>: <span class="hljs-number">5px</span>;
      <span class="hljs-attribute">left</span>: <span class="hljs-number">5px</span>;
      <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">1rem</span>;
      <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
      <span class="hljs-attribute">z-index</span>: <span class="hljs-number">2</span>;
      <span class="hljs-attribute">position</span>: absolute;
      <span class="hljs-attribute">transition</span>: all ease-in <span class="hljs-number">0.3s</span>;
    }

    &amp;<span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">img</span> {
      <span class="hljs-attribute">scale</span>: <span class="hljs-number">1.1</span>;
    }

    &amp;<span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">h2</span> {
      <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(<span class="hljs-number">10px</span>, -<span class="hljs-number">10px</span>);
    }
  }
}

<span class="hljs-selector-class">.single__product</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span>;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">4rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">overflow</span>: hidden;

  &amp; section {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">flex-direction</span>: column;

    &amp; figure {
      <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
      <span class="hljs-attribute">overflow</span>: hidden;

      &amp; .product__img {
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
      }
    }

    &amp; <span class="hljs-selector-tag">aside</span> {
      <span class="hljs-attribute">display</span>: flex;
      <span class="hljs-attribute">flex-direction</span>: column;
      <span class="hljs-attribute">justify-content</span>: flex-end;
      <span class="hljs-attribute">padding</span>: <span class="hljs-number">1.5rem</span>;

      &amp; &gt; h2 {
        <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2.5rem</span>;
      }
      &amp; &gt; <span class="hljs-selector-tag">h3</span> {
        <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.6rem</span>;
      }
      &amp; <span class="hljs-selector-tag">span</span> {
        <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">160</span>, <span class="hljs-number">64</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
        <span class="hljs-attribute">padding-inline</span>: <span class="hljs-number">1rem</span>;
        <span class="hljs-attribute">align-self</span>: flex-start;
      }
    }
  }
}

<span class="hljs-comment">/* Small devices (portrait tablets and large phones, 600px and up) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">600px</span>) {
  <span class="hljs-selector-class">.products__list</span> {
    <span class="hljs-attribute">column-count</span>: <span class="hljs-number">2</span>;
  }

  <span class="hljs-selector-class">.single__product</span> {
    &amp; section {
      <span class="hljs-attribute">flex-direction</span>: row;

      &amp; .product__img {
        <span class="hljs-attribute">max-width</span>: <span class="hljs-number">300px</span>;
      }
    }
  }
}

<span class="hljs-comment">/* Medium devices (landscape tablets, 768px and up) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-selector-class">.homepage</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">4rem</span>;
  }
  <span class="hljs-selector-class">.products__list</span> {
    <span class="hljs-attribute">column-count</span>: <span class="hljs-number">3</span>;
  }
}
</code></pre>
<p>At the moment, your home page should already look identical to the demo version.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/14-page-with-styings-applied.png" alt="Image" width="600" height="400" loading="lazy">
<em>Home page with styles added</em></p>
<h3 id="heading-how-to-store-state-in-the-url">How to store state in the URL</h3>
<p>In order to manage and share state across multiple pages using the URL, you first need to define routes using the react-router package.</p>
<p>Start by creating a route for the homepage:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { BrowserRouter, Route, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> HomePage <span class="hljs-keyword">from</span> <span class="hljs-string">"./HomePage"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">HomePage</span> /&gt;</span>} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<ul>
<li>The <strong>BrowserRouter</strong> component wraps your entire application or the part of your app where you want to use routing.</li>
<li>The <strong>Routes</strong> component wraps all your <strong>Route</strong> components and is responsible for rendering the first route that matches the current location. </li>
<li>The <strong>Route</strong> component represents a single route in your application.</li>
</ul>
<p>Next, create a <code>ProductItem</code> component responsible for showing a single item and its equivalent route.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { BrowserRouter, Route, Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> HomePage <span class="hljs-keyword">from</span> <span class="hljs-string">"./Homepage"</span>;
<span class="hljs-keyword">import</span> ProductItem <span class="hljs-keyword">from</span> <span class="hljs-string">"./ProductItem"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">index</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">HomePage</span> /&gt;</span>} /&gt;
         <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"product"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">ProductItem</span> /&gt;</span>} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
}
</code></pre>
<p>To view the <code>ProductItem</code> component, head over to your <code>HomePage</code> and wrap each individual product with a <code>Link</code> element pointing to the product page with their unique ID.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HomePage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [products, setProducts] = useState([]);

  useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:9000/products"</span>);

      <span class="hljs-keyword">const</span> clothesData = <span class="hljs-keyword">await</span> res.json();
      <span class="hljs-built_in">console</span>.log(clothesData);
      setProducts(clothesData);
    }
    fetchData();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"homepage"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Homepage of my Dummy Product Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"products__list"</span>&gt;</span>
        {products.map((product) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
            <span class="hljs-attr">key</span>=<span class="hljs-string">{product.id}</span>
           // <span class="hljs-attr">Moving</span> <span class="hljs-attr">to</span> <span class="hljs-attr">the</span> <span class="hljs-attr">product</span> <span class="hljs-attr">page</span>
           <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`/<span class="hljs-attr">product</span>?<span class="hljs-attr">id</span>=<span class="hljs-string">${product.id}</span>`}
            <span class="hljs-attr">className</span>=<span class="hljs-string">"product__item"</span>
          &gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">loading</span>=<span class="hljs-string">"lazy"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{product.imageUrl}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{product.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>Clicking on any product now routes you to the product page and shows the <code>ProductItem</code> component.</p>
<p>On closer observation, you may notice that the id of each item is appended to the URL via its id property (for example: product?id=12345678).  This implies that you have successfully stored the id state to the URL.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/02-confirming-id-state-shared.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-read-the-state-stored-in-the-url">How to read the state stored in the URL</h3>
<p>In order to show data for each product, you have to read the state stored in the URL.</p>
<p>To implement this, start by creating a new custom hook (this helps for reusability). In your custom hook, import the <code>useSearchParams</code> hook.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useSearchParams } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useURLID</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [searchParams] = useSearchParams();
}
</code></pre>
<p>The <code>useSearchParams</code> hook allows you to interact with the query parameters of the URL (part of the URL that comes after the ? as seen in your URL earlier).</p>
<p>In order to retrieve the values from the URL, use the <code>get</code> method and pass in the name of the value you want to retrieve, in this case, the <code>id</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useSearchParams } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useURLID</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [searchParams] = useSearchParams();
  <span class="hljs-keyword">const</span> id = searchParams.get(<span class="hljs-string">"id"</span>);
  <span class="hljs-keyword">return</span> { id };
}
</code></pre>
<p>To test out your hook, import it into the <code>ProductItem</code> page and extract the values.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useURLID } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useURLID"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductItem</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { id } = useURLID();
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Product Item {id}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/2-confirming-id-state-shared.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And voilà! Your id state is now global and can used by any component in your app. Bravo!</p>
<h3 id="heading-how-to-customize-the-product-page">How to customize the Product Page</h3>
<p>In order to fully achieve what was shown in the demo, perform another fetch based on the id to get the data for that product.</p>
<p>Start by creating states to store the data and account for the data loading.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [singleProduct, setSingleProduct] = useState({});
<span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<p>Then use a <code>useEffect</code> hook to fetch and store the data based on the unique product id.</p>
<pre><code class="lang-js">  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:9000/products/<span class="hljs-subst">${id}</span>`</span>);

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

        setSingleProduct(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchData();
  }, [id]);
</code></pre>
<p>Next, use the data received to populate the interface.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useURLID } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useURLID"</span>;


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductItem</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { id } = useURLID();
  <span class="hljs-keyword">const</span> [singleProduct, setSingleProduct] = useState({});
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:8000/products/<span class="hljs-subst">${id}</span>`</span>);

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

        setSingleProduct(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchData();
  }, [id]);



  <span class="hljs-comment">// If loading, display the loading div</span>
  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-comment">// If not loading, display the product details</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"single__product"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
               <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
          {singleProduct.itemName} Page id: {id}
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img"</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">{singleProduct.imageUrl}</span>
            <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">figure</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">aside</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{singleProduct.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{singleProduct.notes}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>
            Category: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{singleProduct.type}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Width: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.width}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Length: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.length}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">aside</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Finally, account for easy navigation by providing a back button to go to the home page. You can do this using the <code>useNavigate</code> hook in react-router. This hook provides a function that allows you to programmatically navigate to other parts of your application. </p>
<p>Simply import the <code>useNavigate</code> hook, and initialize it with a variable like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">const</span> navigate = useNavigate();
</code></pre>
<p>Then call this function with an event handler, and pass in the home page route.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useURLID } <span class="hljs-keyword">from</span> <span class="hljs-string">"./useURLID"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductItem</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { id } = useURLID();
  <span class="hljs-keyword">const</span> [singleProduct, setSingleProduct] = useState({});
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`http://localhost:9000/products/<span class="hljs-subst">${id}</span>`</span>);

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

        setSingleProduct(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchData();
  }, [id]);

  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <span class="hljs-comment">// If loading, display the loading div</span>
  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-comment">// If not loading, display the product details</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"single__product"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>
       // Navigate to the home page
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> navigate("/")}&gt;🔙 <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
          {singleProduct.itemName} Page id: {id}
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"product__img"</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">{singleProduct.imageUrl}</span>
            <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">figure</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">aside</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{singleProduct.itemName}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{singleProduct.notes}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>
            Category: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{singleProduct.type}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Width: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.width}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Length: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{singleProduct?.size?.length}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">aside</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Testing your final result now gives the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/final-take-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Final take showing all features</em></p>
<h2 id="heading-real-world-examples">Real-World Examples</h2>
<ul>
<li><strong>E-commerce platforms</strong>: Think of sites like Amazon. They use URLs to let you share specific product searches or settings. Thanks to this, people can easily share their favourite items or shopping lists with friends.</li>
<li><strong>Data Tools</strong>: Tools like <a target="_blank" href="https://www.tableau.com/">Tableau</a> save your custom views in the URL. This means teams can share specific data pictures with each other, making talks, shows, and decisions faster and clearer.</li>
</ul>
<h3 id="heading-additional-information">Additional Information</h3>
<p>I’d like to point out a couple of things in the article not highlighted.</p>
<ul>
<li>The CSS used contains <a target="_blank" href="https://developer.chrome.com/articles/css-nesting/">native CSS nesting</a> that isn’t fully supported by all browsers, so if there are UI irregularities you notice, it may be from the browser you’re using. Feel free to switch to a browser like Google Chrome for better support or check for browser support with a tool like <a target="_blank" href="https://caniuse.com/">CanIUse</a> and add polyfills to your code.</li>
<li>If this article delved into things that were a tad complicated for you (how routing works), feel free to check out this article on <a target="_blank" href="https://www.freecodecamp.org/news/improve-user-experience-in-react-by-animating-routes-using-framer-motion/">Routing Animations</a> for a better understanding.</li>
<li>If you’re interested in the full code, here’s the repo, <a target="_blank" href="https://github.com/Daiveedjay/URL-State-Management">GitHub</a>, and the Live version is here. <a target="_blank" href="https://free-code-camp-url-state-manangement.netlify.app/">Demo</a></li>
<li>As an added feature, I made the code fully responsive for anyone interested in creating masonry grids for future projects, cheers!🍷</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>React's state management has evolved, with URL-based state emerging as a standout. This method not only simplifies state management but also fosters collaboration and transparency between users and developers.</p>
<p>So, the next time you're online and think of sharing data via a URL, remember that you have the tools to implement this feature yourself 😉. It's a nudge for developers to explore the untapped potential of URLs in state management.</p>
<h3 id="heading-contact-information">Contact Information</h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter / X: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: <a target="_blank" href="mailto:Jajadavidjid@gmail.com">Jajadavidjid@gmail.com</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Routing in Next.js – How to Use App Router in your Next Apps ]]>
                </title>
                <description>
                    <![CDATA[ In the ever-evolving world of web development, Next.js has consistently been a beacon of hope for developers seeking a balance between performance and ease of use.  With the introduction of the App Router in 2023, the framework has once again stirred... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/routing-in-nextjs/</link>
                <guid isPermaLink="false">66bb891a6b3bd8d6bf25ae3d</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Thu, 24 Aug 2023 15:13:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/Article-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In the ever-evolving world of web development, Next.js has consistently been a beacon of hope for developers seeking a balance between performance and ease of use. </p>
<p>With the introduction of the App Router in 2023, the framework has once again stirred the pot, leaving many of us scratching our heads and pondering, "Do we stick with the tried-and-true Pages directory or embrace the shiny new App Router?". </p>
<p>In this exploration, we will delve into the unique facets of the App Router, offering valuable guidance for navigating these new features.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>A good understanding of JavaScript.</li>
<li>A good understanding of React.js and Next.js.</li>
</ul>
<h2 id="heading-a-brief-look-at-routing">A Brief Look at Routing</h2>
<p>Routing is a critical aspect of web apps that enables users to move between various pages. It guarantees that users can access different parts of an application, whether they are moving from a homepage to a product listing or navigating within single-page applications. </p>
<p>The Pages Directory and App Router are two crucial components that determine how users navigate through a Next.js application.</p>
<h2 id="heading-how-the-pages-directory-works-in-nextjs">How the Pages Directory Works in Next.js</h2>
<p>While the spotlight shines on the new App Router, let's not forget the solid foundation provided by the Pages Directory. A key difference between the two lies in route generation.</p>
<p>The Pages Directory automatically creates routes within the <code>pages</code> folder, whereas the App Router organizes routes within the <code>app</code> folder. This folder routing system maintains developer familiarity with how routing works while introducing a shift in route organization.</p>
<p>This distinction enables efficient route management and facilitates a seamless transition between the two routing mechanisms.</p>
<h3 id="heading-how-to-set-up-the-pages-directory">How to Set Up the Pages Directory</h3>
<p>To set up the Pages Directory for routing, you must first create a Next application. You can do this by running the command below on your local or code editor's terminal:</p>
<pre><code class="lang-bash">npx-create-next-app your-app-name
</code></pre>
<p>A list of configuration options appear underneath your command. Select "No" for <code>App Router</code> during the application setup. This creates a pages folder from which you can create routes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Folder-Directory-Setup-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder directory installation and setup</em></p>
<h3 id="heading-how-to-create-a-route-with-pages-directory">How to Create a Route with Pages Directory</h3>
<p>To create a route, create a folder in the pages folder and call it whatever you want the route to be (<strong>about</strong>, for example).</p>
<p>Then nest an <strong>index.js</strong> file in the <strong>about</strong> folder and fill it in with whatever content you want.</p>
<p>To route between pages, you can use the Next.js <code>link</code> component and pass in the corresponding URL you wish to route to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Folder-Directory-Example---3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder directory example</em></p>
<p>Here's the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Implementing-folder-routing.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Implementing routing using the folder directory</em></p>
<h3 id="heading-limitations-of-the-pages-directory">Limitations of the Pages Directory</h3>
<p>The Pages Directory provides a great way to structure routes in a Next.js application, but it has some limitations. Here are a few things to keep in mind:</p>
<ul>
<li>Static exports: The Pages Directory configuration relies on dynamic routes generated using <code>getStaticProps</code> and <code>getStaticPaths</code>. This means that not all pages in the directory can be statically exported.</li>
<li>Edge Runtime configuration: If you're using the Edge Runtime, you may need to do extra configuration beyond what's possible in the Pages Directory.</li>
<li>Internationalization routing: While Next.js supports internationalization routing, you need to configure locales, default locales, and domain-specific locales in the <strong>next.config.js</strong> file instead of the Pages Directory.</li>
<li>Serverless functions: API routes defined in the Pages Directory can handle basic API functionality, but more complex serverless functions may need extra configuration and alternative file placement.</li>
<li>Statically generated pages distribution: Statically generated pages may not be optimized for visitors without additional CDN configuration or "vendoring". This can impact the performance and distribution of statically generated pages. </li>
</ul>
<h2 id="heading-how-the-app-router-works-in-nextjs">How the App Router Works in Next.js</h2>
<p>The App Router is the fresh face on the Next.js scene, designed to address some of the limitations of the Pages Directory approach. While the app router still uses the folder directory for routing, it does so with a slightly different convention.</p>
<h3 id="heading-how-to-setup-the-app-router">How to Setup the App Router</h3>
<p>To set up the App router , follow the same installation process as mentioned in the pages directory, but opt for "Yes" when prompted to use the <code>App Router</code> during setup. This creates an <strong>app</strong> directory.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/App-router-Setup-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>App Router installation and setup</em></p>
<h3 id="heading-how-to-create-a-route-with-app-router">How to Create a Route with App Router</h3>
<p>Routing with the App Router also involves creating folders but within the <strong>app</strong> directory. Nest a <strong>page.js</strong> file within the appropriate folder to define your route.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/App-router-Example-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Folder directory example</em></p>
<p>Here's the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Implementing-app-routing.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Implementing routing using the app router</em></p>
<h2 id="heading-features-of-app-router-in-nextjs">Features of App Router in Next.js</h2>
<p>Apart from routing, App Router boasts a range of other features, including:</p>
<h3 id="heading-layout-component">Layout Component</h3>
<p>A layout component is a versatile UI element that shapes a page's structure. It can include components like headers, footers, and sidebars, and even offer shared functions like navigation.</p>
<p>Layout components work with routing, enabling smooth transitions between app pages. Since the layout component remains active when routes change, its state is retained, ensuring consistent and reusable layouts with minimal effort. </p>
<p>This component is designed to receive a <code>children</code> prop and wrap all page files in the same directory with it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">layout</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"layout"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}
</code></pre>
<p>Here’s an example that uses a layout component (a grey box) like the one in the code above between the user page and the settings page:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Layout-example-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a layout component that shares styles with its sibling pages</em></p>
<p>In the image above, the <strong>layout.js</strong> component is shared by both the user and settings pages. So both pages will have the styles and logic in the layout component.</p>
<p>And the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Implementing-layouts.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Implementing the layout component on the user and settings page</em></p>
<h3 id="heading-nested-layouts">Nested Layouts</h3>
<p>These are layouts defined inside folders and apply to specific route segments and render when those segments are active. It allows you to define multiple levels of layout components, each enclosing the content of its child components. </p>
<p>This feature provides a flexible and modular way to structure your application's UI.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/nested-layouts.png" alt="Image" width="600" height="400" loading="lazy">
<em>Demonstrating how layout work with sibling and child pages</em></p>
<p>In the diagram above, the styles and logic in the first layout file applies to all pages inside the <strong>dashboard</strong> directory, while the second layout file applies to the pages in the <strong>developer</strong> directory.</p>
<h3 id="heading-template-components">Template Components</h3>
<p>Template components are like layouts, but they create a new instance for each child on navigation. This means recreating DOM elements, losing state, and resetting effects every time the route changes. </p>
<p>You can use them for things like tracking page views or interactive widgets. You can create a template by exporting a default React component from a <code>template.js</code> file. This component should be designed to receive a children prop.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Template</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<h3 id="heading-loading-component">Loading Component</h3>
<p>This component can be made in any app folder directory. It auto-wraps pages with a React suspense boundary (that is, a component that helps manage loading moments when components need to fetch data or resources asynchronously). It shows on the first load and during sibling route navigation.</p>
<p>It looks something like this under the hood:</p>
<pre><code class="lang-js">&lt;Suspense fallback={<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Loading</span> /&gt;</span></span>}&gt;
   <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">YourComponent</span> /&gt;</span></span>
&lt;/Suspense&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/loading-component.png" alt="Image" width="600" height="400" loading="lazy">
<em>Showcasing the loading component in use</em></p>
<h3 id="heading-streaming">Streaming</h3>
<p>This involves sending parts of a webpage progressively from the server to the user's device. Unlike the traditional Server-Side Rendering (SSR), where all the data must be fetched before rendering, streaming sends smaller chunks of HTML as they're ready. </p>
<p><strong>Before streaming</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Before-streaming.png" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying how SSR worked before stream was introduced</em></p>
<p>In the image above, no content is displayed while the page is being rendered. The component waits until all the contents are ready.</p>
<p><strong>Using streaming</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/using-streaming.png" alt="Image" width="600" height="400" loading="lazy">
<em>How SSR now works with streaming</em></p>
<p>In the image above, the component doesn't wait for all the page content, it renders each one as soon as it's ready. </p>
<p>This speeds up the initial page display, prioritizing higher-priority components for early interactivity. Streaming reduces [Time To First Byte](https://en.wikipedia.org/wiki/Time_to_first_byte#:~:text=Time%20to%20first%20byte%20(TTFB,received%20by%20the%20client's%20browser.) (TTFB), enhances interactivity, and works well with React's component model.</p>
<p>It's works by using the <code>&lt;Suspense&gt;</code> component, improving loading and user experience, especially on slower devices.</p>
<h3 id="heading-error-component">Error Component</h3>
<p>This component confines errors to the app's tiniest section. Making an error file auto-encloses the page with a React error boundary. Any error within this file's folder swaps the component with its contents.</p>
<p>The error component is rendered like this behind the scenes:</p>
<pre><code class="lang-js">&lt;Layout&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Error</span> /&gt;</span>}&gt;
    <span class="hljs-tag">&lt;<span class="hljs-name">Page</span>/&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span></span>
&lt;/Layout&gt;
</code></pre>
<p>And shows something like this;</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/error-layout.png" alt="Image" width="600" height="400" loading="lazy">
<em>Showcasing the error component in the case of an error</em></p>
<h3 id="heading-route-groups">Route Groups</h3>
<p>Route Groups organize routes in the app directory without altering URL paths. Enclosing a folder name in parentheses creates a Route Group that keeps related routes together. </p>
<p>This allows for logical grouping, nested layouts, and a clean URL structure. That is:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/route-groups.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to use route groups to organize routes</em></p>
<p>In the example above, authentication pages are grouped together for better organization, without altering URL structure.</p>
<h3 id="heading-server-components">Server Components</h3>
<p>Server components, a prime addition to the App Router, renders on the server and streams to the client. This accelerates page loading and enhances performance. They speed up page load times as different page contents are loaded in small chunks and independently.</p>
<p>Note that they don't support client-side actions like click events and React hooks (<code>useState</code> , <code>useRef</code>). To convert a server component into a client component, mark it with <code>use client</code> at the beginning of the file. </p>
<p>Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-string">'use client'</span>

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>)

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You clicked {count} times<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<h3 id="heading-data-fetching">Data Fetching</h3>
<p>Server components bring a fresh data fetching pattern, allowing <code>async</code> components to fetch data within them. This reduces reliance on APIs like <code>getServerSideProps</code>. </p>
<p>To fetch data, mark a component as <code>async</code> and use the fetch function within:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://api.adviceslip.com/advice"</span>);
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Home Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{data.slip.advice}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>And get your result on the page like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/fetch.png" alt="Image" width="600" height="400" loading="lazy">
<em>Using the fetch function in a server component</em></p>
<p>The App Router also caches the fetched data on the server, eliminating the need to re-fetch that data on every request, unless a revalidation parameter is passed in in the fetch function:  </p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://api.adviceslip.com/advice"</span>, {
    <span class="hljs-attr">next</span>: { <span class="hljs-attr">revalidate</span>: <span class="hljs-number">5</span> },
  });
</code></pre>
<p>The code above causes a re-fetch of new data every 5 seconds.</p>
<h3 id="heading-built-in-seo">Built-in SEO</h3>
<p>Another feature of the Next.js App router is the built-in Metadata API, used as an SEO tool to optimize websites for search engines. This API provides a range of SEO settings, including the <a target="_blank" href="https://ogp.me/">Open Graph protocol</a>, to enhance the visibility of websites to search engines.</p>
<p>There are two methods of implementing this — static and dynamic methods.</p>
<p>Here's the static approach:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Metadata } <span class="hljs-keyword">from</span> <span class="hljs-string">"next"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Metadata = {
  <span class="hljs-attr">title</span>: <span class="hljs-string">"Blog page title"</span>,
  <span class="hljs-attr">description</span>: <span class="hljs-string">"Blog page description"</span>,
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">page</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Blog Page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here's the dynamic approach using the <code>getMetadata</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateMetadata</span>(<span class="hljs-params">{ params, searchParams}</span>) </span>{

<span class="hljs-keyword">const</span> id= params.id

   <span class="hljs-keyword">const</span> blog= <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`https://blog/<span class="hljs-subst">${id}</span>`</span>).then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span>res.json()

  <span class="hljs-keyword">return</span> { 
        <span class="hljs-attr">title</span>: blog.title,
        <span class="hljs-attr">Description</span>: blog.description,
   };

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Page</span>(<span class="hljs-params">{ params, searchParams }</span>) </span>{}
</code></pre>
<h2 id="heading-advanced-features-of-app-router-in-nextjs">Advanced Features of App Router in Next.js</h2>
<p>While we've covered notable aspects, the App Router's capabilities extend beyond what we've discussed. Features like server actions, data revalidation, parallel routes, and route interception provide further utility.</p>
<p>As always, you can turn to the <a target="_blank" href="https://nextjs.org/docs">Next.js docs</a> for a wider range of information to elevate your understanding and mastery of these additions to the Next.js ecosystem.</p>
<h2 id="heading-pages-directory-vs-app-router-which-to-use">Pages Directory vs App Router - Which to Use?</h2>
<p>In the rapidly evolving world of web development, it's easy to get caught up in the hype surrounding new technologies and tools. However, when it comes to choosing between the Pages Directory and the App Router, it's important to strike a balance between excitement and caution.</p>
<p>Both options have their own strengths and considerations, and understanding your needs and goals will help you determine which one to use in a given context.</p>
<h3 id="heading-selecting-the-appropriate-tool-for-your-requirements">Selecting the Appropriate Tool for Your Requirements</h3>
<p>When making the choice between the Pages Directory and the App Router, it is crucial to take into account your individual needs and objectives. Here are a few factors to bear in mind:</p>
<ol>
<li><p>Stability vs Flexibility: If your main concerns are stability and user-friendliness, the Pages Directory is a dependable option. It provides a solid foundation for simple routing tasks. However, if you require more flexibility and the ability to customize, the App Router might be a more suitable choice.</p>
</li>
<li><p>Development speed: The Pages Directory offers a fast and efficient approach to creating and managing pages, making it ideal for speedy development. Conversely, due to its advanced capabilities, the App Router may cause more upfront configuration and development effort.</p>
</li>
<li><p>Complex routing scenarios: If your application requires intricate routing scenarios like nested routes or dynamic routing based on external data, the App Router's programmability can be a significant advantage.</p>
</li>
</ol>
<p>Ultimately, the key to making well-informed decisions lies in staying knowledgeable about the capabilities and trade-offs of both the Pages Directory and the App Router.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, you now have a good understanding of Next.js's App Router and its features.</p>
<p>You have learned how to structure routes using both the Pages Directory and the App Router, as well as advanced features such as layout components, server components, and data fetching.</p>
<p>By exploring these topics, you have not only gained insights into the capabilities of these tools. You've also learned how to choose between the new approach (App Router) and the old approach of using the Pages Directory.</p>
<p>With this knowledge, you are well-prepared to make informed decisions and create exceptional web experiences in the ever-changing landscape of web development. </p>
<h2 id="heading-contact-information">Contact Information</h2>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter, sorry (X) 😂: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: Jajadavidjid@gmail.com</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Routing System for a PHP App from Scratch ]]>
                </title>
                <description>
                    <![CDATA[ By Abel Lifaefi Mbula If you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like server/contact.php. No worries, we all started that way, and it’s how... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-routing-system-in-php/</link>
                <guid isPermaLink="false">66d45d593a8352b6c5a2a9eb</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 02 May 2023 08:36:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Abel Lifaefi Mbula</p>
<p>If you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like <code>server/contact.php</code>. No worries, we all started that way, and it’s how we learn.</p>
<p>Today, I want to help you improve how you navigate files in your application. We’ll be talking about routing, as it’s crucial in any modern application. It'll help you take a step forward in your professional PHP development. </p>
<p>A routing system simply maps an <a target="_blank" href="https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html">HTTP</a> request to a request handler (function or method). In other words, it defines how we navigate or access different parts of an app without the need to type the file name. You can do this by creating or setting routes (or paths). For example, the route <code>server/contact</code> lets us access the <code>contact.php</code> file.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most out of this tutorial, you'll need the following:</p>
<ul>
<li>A basic understanding of PHP.</li>
<li>A basic understanding of HTTP and networking.</li>
<li>An Apache or NGINX server, and a basic understanding of how to configure those.</li>
</ul>
<p>And with that, let's jump in.</p>
<h2 id="heading-how-routing-works">How Routing Works</h2>
<p>First thing first, let me recall you what a routing is. Routing allows us to structure our app in a better way and get rid of messy URLs. These are two main features offered by any good routing system:</p>
<ul>
<li>Defines which action to run for each incoming request.</li>
<li>Generates SEO-friendly URLs (e.g. <code>/views/users</code> instead of <code>views/user.php?all</code>).</li>
</ul>
<p>To do a routing system, we need a router, which is no more than the entry file to our app. By default, this entry file is named as <code>index.php</code>. Inside the file, we define the routing system thanks to <code>[switch](https://www.php.net/manual/en/control-structures.switch.php)</code> or <code>[match](https://www.php.net/manual/en/control-structures.match.php)</code> statements. </p>
<p>Last but not least, we must redirect all requests to the router. This is done in the configuration file of the PHP server.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Before moving forward, let’s see what the project will look like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/file-tree-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>File structure</em></p>
<p>Use the shell commands below to initiate the project:</p>
<pre><code class="lang-bash">mkdir php-routing &amp; <span class="hljs-built_in">cd</span> php-routing
touch index.php .htaccess
</code></pre>
<ul>
<li><code>.htaccess</code>: A directory-level Apache configuration file. You don’t need it if you use an NGINX server.</li>
<li><code>index.php</code>: This is the router and entry file of the project. All incoming requests will be redirected here.</li>
<li><code>views</code>: This folder holds all the UIs for the project.</li>
</ul>
<h2 id="heading-how-to-redirect-all-http-requests-to-the-router"><strong>How to Redirect All HTTP Requests to the Router</strong></h2>
<p>We've said earlier that the redirection is done in the PHP server config file. So you'll need to make some tweaks depending on whether you use an Apache or NGINX server.</p>
<h3 id="heading-redirect-using-apache">Redirect Using Apache</h3>
<p>Here, we can easily use the <code>.htaccess</code> file that we have already created in the root of the project. Add the directives below:</p>
<pre><code class="lang-bash">RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)＄ index.php
</code></pre>
<ul>
<li><em>line 1</em>: We activate the Apache server’s runtime rewriting engine. </li>
<li><em>line 2</em>: We limit access to physical files. </li>
<li><em>line 3</em>: We redirect all the upcoming requests to the <code>index.php</code>.</li>
</ul>
<p>Note: If the site or app is note at the root of the server (or if we don’t have a virtual host), here's what the <code>.htaccess</code> should look like:</p>
<pre><code class="lang-bash">RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</code></pre>
<p>In the code above, replace <code>/folder/</code> with the name of the folder containing your site.</p>
<h3 id="heading-redirect-using-nginx">Redirect Using NGINX</h3>
<p>The default configuration file is name <code>nginx.conf</code>. This file can be found in <code>etc/nginx</code>, <code>usr/local/nginx/conf</code>, or <code>/usr/local/etc/nginx</code>.</p>
<p>To redirect to <code>index.php</code> use the command below:</p>
<pre><code class="lang-nginx"><span class="hljs-attribute">location</span> / {
        <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php
}
</code></pre>
<p>The <code>location /</code> block specifies that this is a match for all locations unless explicitly specified <code>location /&lt;name&gt;</code>.</p>
<p>The <code>try_files</code> directive tells the server that for any request to the URI that matches the block in the location, try the <code>$uri</code> (or <code>$uri/</code>) first, and if the file is present, serve the file. Otherwise, the fallback option (<code>index.php</code>) is used. And this last behavior is what we want.</p>
<p>Reload the server after the modification.</p>
<h2 id="heading-how-to-create-the-routing-system"><strong>How to Create the Routing System</strong></h2>
<p>We now know how routing works, and we are even sending all requests to the router. Now is the time to write the code for the router in <code>index.php</code>.</p>
<p>First, create a variable to hold the HTTP request string:</p>
<pre><code class="lang-php">$request = $_SERVER[<span class="hljs-string">'REQUEST_URI'</span>];
</code></pre>
<p>This variable will help us to compare with many routes (paths) and call the appropriate view interface. </p>
<pre><code class="lang-php"><span class="hljs-keyword">switch</span> ($request) {
     <span class="hljs-keyword">case</span> <span class="hljs-string">'/views/users'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/views/users.php'</span>;

     <span class="hljs-keyword">case</span> <span class="hljs-string">'/views/department'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/views/dep.php'</span>;
}
</code></pre>
<p>What's happening here? The <code>switch</code> statement is similar to a series of <code>if</code> statements on the same expression (variable). It executes a code only when a <code>case</code> statement is found whose expression evaluates to a value that matches the value of the <code>switch</code> expression. Let me illustrate this so that you can get it well. </p>
<p>Let's consider that our variable holds the value <code>/views/users/</code>. When the piece of the code above will be run, PHP will check if the value <code>/views/users</code> equals to the value of <code>case</code> statement, which in our case is <code>/views/users</code>. So, this condition will evaluate to <code>true</code>, PHP will call the file <code>/views/users.php</code>. If the condition evaluates to <code>false</code>, PHP will check for the next <code>case</code> statement until the end of the <code>switch</code> block. </p>
<p><strong>Note</strong>: Every time the <code>case</code> statement evaluates to <code>true</code> PHP will continue to execute the code in the following <code>case</code> statements without necessary evaluating those <code>case</code> statements. In our case, PHP also requires <code>views/dep.php</code>. To avoid this "bad behavior", you must add <code>break</code> statement after each <code>case</code> statement.</p>
<p>Let now put everything together into our <code>index.php</code> file:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

$request = $_SERVER[<span class="hljs-string">'REQUEST_URI'</span>];
$viewDir = <span class="hljs-string">'/views/'</span>;

<span class="hljs-keyword">switch</span> ($request) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">''</span>:
    <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'home.php'</span>;
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">'/views/users'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'users.php'</span>;
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">'/contact'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'contact.php'</span>;
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">default</span>:
        http_response_code(<span class="hljs-number">404</span>);
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'404.php'</span>;
}
</code></pre>
<p>As you already know, we start off by storing a user request in the <code>$request</code> variable, then we use it in the <code>switch</code> statement. For the sake of clean code, I have created a variable to hold the view directory name.</p>
<p>You'll also notice two other things:</p>
<ul>
<li>Both <code>''</code> and <code>'/'</code> are used to match <code>site.com</code> as well as <code>site.com/</code> for when users are in the root of the app or website.</li>
<li>There's a special <code>case</code> statement, <code>default</code>, to match anything that wasn't matched by the other cases, i.e. when the route is unknown.</li>
</ul>
<p>Let's now add some dummy data in our views.</p>
<h2 id="heading-add-dummy-data-in-the-views-files"><strong>Add Dummy Data in the Views Files</strong></h2>
<p>We have already created all files in the <code>views</code> directory. Let's just move to this directory and add some content in each file.</p>
<p>Just put some content in each file:</p>
<pre><code class="lang-php">&lt;h1&gt;Home&lt;/h1&gt;
&lt;p&gt;Welcome in my app.&lt;/p&gt;
</code></pre>
<pre><code class="lang-php">&lt;h1&gt;Users&lt;/h1&gt;
&lt;p&gt;<span class="hljs-keyword">List</span> of our users.&lt;/p&gt;
</code></pre>
<pre><code class="lang-php">&lt;h1&gt;Conct us&lt;/h1&gt;
&lt;p&gt;Getting in touch is easy. Just email us&lt;/p&gt;
</code></pre>
<pre><code class="lang-php">&lt;h1&gt;<span class="hljs-number">404</span>&lt;/h1&gt;
&lt;p&gt;You<span class="hljs-string">'ve reached the end of Internet.&lt;/p&gt;</span>
</code></pre>
<p>As you can see, each file just contains a title and a paragraph. Feel free to add whatever content you like and test the router.</p>
<h2 id="heading-final-thoughts"><strong>Final thoughts</strong></h2>
<p>In this tutorial, you learned how to create a basic routing system from scratch, including:</p>
<ul>
<li>How to create a file named <code>index.php</code> at the root of the project. This is the router for your app.</li>
<li>How to redirect all incoming requests to the router. You do this in the configuration file of your server.</li>
<li>How to create the routing system with a <code>switch</code> statement in the router.</li>
</ul>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Routing in Next.js – How to Set Up Dynamic Routing with Pre-Rendering in Next ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you'll learn how to set up dynamic routing in Next.js. You'll also learn about pre-rendering and why it's important. 🔐 Here's what we'll cover: You'll get to know getStaticPaths(), one of the core principles of Next.js. You'll imp... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-dynamic-routing-in-nextjs/</link>
                <guid isPermaLink="false">66bb8f3f5d242388375d3878</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Matthes B. ]]>
                </dc:creator>
                <pubDate>Fri, 29 Jul 2022 21:21:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/pexels-pixabay-2150.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you'll learn how to set up dynamic routing in Next.js. You'll also learn about pre-rendering and why it's important.</p>
<h2 id="heading-heres-what-well-cover">🔐 Here's what we'll cover:</h2>
<ul>
<li>You'll get to know <code>getStaticPaths()</code>, one of the core principles of Next.js.</li>
<li>You'll improve your general Next.js knowledge and confidence.</li>
<li>You'll have access to a quick-replicable example for your own Next.js learning purposes.</li>
</ul>
<h2 id="heading-prerequisites"><strong>📝</strong> Prerequisites</h2>
<ul>
<li>You should be familiar with what Next.js is and why you should consider using it.</li>
<li>You should have some understanding of what <a target="_blank" href="https://nextjs.org/docs/routing/introduction"><strong>Routing</strong></a> and <a target="_blank" href="https://nextjs.org/docs/routing/dynamic-routes"><strong>Dynamic Routing</strong></a> mean in React and/or Next.js.</li>
<li>For this example, I work with TypeScript. But it's not necessary for you to be familiar with TypeScript. I will address the code which would be omitted when using JavaScript. Also, whenever you see <code>.tsx</code> regarding any files, you can just replace that with <code>.js</code> if you are using JavaScript.</li>
</ul>
<h2 id="heading-the-objective"><strong>🎯</strong> The Objective</h2>
<p>This quick guide aims to help you manage fetching data, which can be used for pre-rendering purposes within dynamic routes in Next.js. We'll discuss some theory as well as a practical example.</p>
<p>While we are focusing on the actual logic of the required code, I won't do any CSS styling whatsoever. Feel free to get creative on the frontend for your own project when you're using the techniques we discuss in this tutorial.</p>
<h2 id="heading-how-routing-works-in-nextjs">🔎 How Routing Works in Next.js</h2>
<p>While React itself uses a code-based approach for any routing intentions, Next.js utilizes a file-system for the concept of routing.</p>
<p>Therefore, you are probably familiar with code-based routing in React, which may look similar to this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/React-Routing.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Example for code-based React Routing</em></p>
<p>With this code-based approach, you are, for example, able to navigate from the main route at <code>/</code> to the <code>about</code> page through <code>/about</code>.</p>
<p>You are also able to find a dynamic routing approach in this React example with the <code>:productId</code> path.</p>
<p>With Next.js, though, we don't use such code-based routing anymore. Instead, this React framework makes use of file-based routing. This means that you set up your routes directly through page files. </p>
<p>Consider the following <code>pages</code> folder containing subfolders and files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/Nextjs-Routing.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Example for file-based Next.js Routing</em></p>
<p>The <code>index.tsx</code> file would be the equivalent to the <code>/</code> path in the React Routing example from above. So you would be able to reach the content within the <code>user-profile.tsx</code> file through <code>/user-profile</code> – that's it! </p>
<p>On the other hand, if you want to reach out to some nested content, you can use <code>/stars/[id]</code> in order to find the content in the corresponding page file.</p>
<p>Maybe you noticed that I'm using square brackets for <code>[id].tsx</code> as well as for <code>[something].tsx</code>. That's needed in order to set up dynamic routing in Next.js. </p>
<p>You could technically insert any input you would like for <code>[id]</code> and the page would load for this specific path. </p>
<p>Just keep in mind that if this dynamic route requires a valid input for <code>[id]</code> (maybe some sort of existing product id for which we want to fetch the respective data), then there could be an error.</p>
<h2 id="heading-data-fetching-in-nextjs-with-dynamic-routing">✂️ Data Fetching in Next.js with Dynamic Routing</h2>
<p>Imagine you apply this dynamic routing approach to a shop page where you list a bunch of different items. Each item would have a link for more information about that specific item. </p>
<p>Within this Link element, you would be able to lead the user to a dynamic route with a valid parameter (the corresponding product id, for example). For such cases, dynamic routing is the best approach.</p>
<h3 id="heading-how-does-getstaticprops-work">❗How does <code>getStaticProps()</code> work?</h3>
<p>With this function, you can pre-render a page at build time. This is useful for Search Engine Optimization (SEO) purposes, for example, and can overall generate a better user experience.</p>
<p>The data which should be pre-rendered can typically be found on some database, for example. Like with <code>getStaticProps()</code>, you are able to directly write any server-side code within this function for data fetching purposes (instead of reaching out to an API route on the backend, which then goes through any required server-side actions).</p>
<p>There is more to say about <code>getStaticProps()</code>. If you are pretty new to all this stuff, I highly recommend checking out the <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching/get-static-props">official Next.js documentation</a> on this topic.</p>
<h3 id="heading-whats-the-purpose-of-getstaticpaths">❓ What's the purpose of <code>getStaticPaths()</code>?</h3>
<p>While <code>getStaticProps()</code> on its own seems to already do all the work we need to be done for our pages, we will encounter an error when we use this function alone on dynamic routing pages. The error message will actually call you out on this specific fact that <code>getStaticPaths()</code> is missing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/error-message.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of server error. SSG stands for Static-Site Generation</em></p>
<p><code>getStaticProps()</code> utilizes the static-site generation concept. So Next.js will pre-render the respective page at build time. In the case of dynamic routes, however, Next.js doesn't know by itself which paths to pre-render. Instead, you have to step in and help – and this is where <code>getStaticPaths()</code> comes in handy.</p>
<p>So with <code>getStaticPaths</code> you can specify which paths of the dynamic routing should be pre-rendered and/or how unknown paths should be handled.</p>
<h3 id="heading-quick-side-note">📋 Quick side note</h3>
<p>If you are using <code>getServerSideProps()</code>, which can be used for similar reasons as <code>getStaticProps()</code>, you will notice that <code>getStaticPaths()</code> is actually not needed. Why is that?</p>
<p><code>getServerSideProps()</code> doesn't use the static generation principle. Instead of building the page, Next.js pre-renders the page on each request with the returned data. This is called server-side rendering.</p>
<p>We don't have to tell Next.js which paths have to be statically pre-rendered while using <code>getServerSideProps()</code>, since there is no such thing for this function in the first place.</p>
<p>If you want to read more about this function, I can again recommend the official Next.js documentation for s<a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props">erver-side rendering</a>. However, this is out of the scope of this quick guide and I won't need <code>getServerSideProps()</code> for any of the following steps.</p>
<h2 id="heading-how-to-setup-our-project">🔧 How to Setup Our Project</h2>
<p>For this example, we will reproduce a small dynamic routing case. For this, I prepared a subfolder <code>test</code> in the <code>pages</code> folder. The <code>pages</code> folder gets automatically created by Next.js. </p>
<p>In the <code>test</code> folder, I insert the <code>[something].tsx</code> file (<code>[something].js</code> if you are using JavaScript and not TypeScript).</p>
<p>There is also a <code>backendData</code> folder at the root level of our Next.js application with the <code>some-backend-data.json</code> file (thus not in the <code>pages</code> folder). This file will provide us with the data which we will insert dynamically.</p>
<h3 id="heading-setup-for-the-backend-json-data">🔨 Setup for the backend <code>JSON</code> data</h3>
<p>For this example, I'm creating some dummy data which will be embedded in the <code>some-backend-data.json</code> within the <code>backendData</code> folder. This way, we can reproduce a situation where you have access to some sort of data in the backend that you want to use on the frontend.</p>
<p>Here's what the <code>some-backend-data.json</code> file looks like:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"stars"</span>: [
        { 
            <span class="hljs-attr">"id"</span>: <span class="hljs-string">"St2-18"</span>, 
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Stephenson 2-18"</span>, 
            <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Stephenson 2-18 is a red supergiant (RSG) or possible extreme red hypergiant (RHG) star in the constellation of Scutum."</span>, 
            <span class="hljs-attr">"link"</span>: <span class="hljs-string">"https://en.wikipedia.org/wiki/Stephenson_2-18"</span> 
        },
        { 
            <span class="hljs-attr">"id"</span>: <span class="hljs-string">"UY-SC"</span>, 
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"UY Scuti"</span>, 
            <span class="hljs-attr">"description"</span>: <span class="hljs-string">"UY Scuti is an extreme red hypergiant or red supergiant star in the constellation Scutum."</span>, 
            <span class="hljs-attr">"link"</span>: <span class="hljs-string">"https://en.wikipedia.org/wiki/UY_Scuti"</span>
        },
        { 
            <span class="hljs-attr">"id"</span>: <span class="hljs-string">"RSGC1"</span>, 
            <span class="hljs-attr">"name"</span>: <span class="hljs-string">"RSGC1-F01"</span>, 
            <span class="hljs-attr">"description"</span>: <span class="hljs-string">"RSGC1-F01 is a red supergiant located in the RSGC1 open cluster in the constellation of Scutum."</span>, 
            <span class="hljs-attr">"link"</span>: <span class="hljs-string">"https://en.wikipedia.org/wiki/RSGC1-F01"</span>
        }
    ]
}
</code></pre>
<p>In this file you will find some <code>JSON</code> formatted data. There is <code>"stars"</code> which is just an array with three objects. All three objects have the same format and include an <code>id</code>, a <code>name</code>, a <code>description</code>, and a <code>link</code> to an external web page.</p>
<p>As you may have figured out by now, these are actually some real stars in our universe.</p>
<p>In a real-world situation, you would probably have some sort of connection to a databank, but the actual data you are receiving from this databank could technically be formatted as in this example. So this is sufficient for our example setup.</p>
<h3 id="heading-imports-and-interface">🔑 Imports and interface</h3>
<p>As a next step, we can dive into actually creating the Next.js <code>[something].tsx</code> dynamic route. Let's start with the required imports for this example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { GetStaticProps, GetStaticPaths  } <span class="hljs-keyword">from</span> <span class="hljs-string">'next'</span>;
<span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/router'</span>;
<span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">'path'</span>;
<span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">'fs/promises'</span>;

<span class="hljs-keyword">interface</span> starInterface {
    id: <span class="hljs-built_in">string</span>
    name: <span class="hljs-built_in">string</span>
    description: <span class="hljs-built_in">string</span>
    link: <span class="hljs-built_in">string</span>
}
</code></pre>
<p>Keep in mind that I'm using TypeScript here. If you are using JavaScript, that's of course fine as well. Just remember that you don't need the <code>interface starInterface</code> or <code>import { GetStaticProps, GetStaticPaths } from 'next'</code>.</p>
<h3 id="heading-how-to-create-the-data-fetching-function">💎 How to Create the Data Fetching Function</h3>
<p>For the next step, I will prepare an <code>async</code> function called <code>getData()</code>, which will be helpful for the <code>getStaticProps()</code> and <code>getStaticPaths()</code> functions. This will look quite confusing, especially if you have never had contact with backend JavaScript code like you would expect in any Node.js application, for example. </p>
<p>Just bear with me for a few more seconds. You don't have to understand the following code in detail. We just need to know what the result of the <code>getData()</code> function is.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> filePath = path.join(process.cwd(), <span class="hljs-string">'backendData'</span>, <span class="hljs-string">'some-backend-data.json'</span>);
    <span class="hljs-keyword">const</span> fileData = <span class="hljs-keyword">await</span> fs.readFile(filePath);
    <span class="hljs-keyword">const</span> data = <span class="hljs-built_in">JSON</span>.parse(jsonData.toString());

    <span class="hljs-keyword">return</span> data;
  }
</code></pre>
<p>As you can see, there are three variables: <code>filePath</code>, <code>fileData</code>, and <code>data</code>. With <code>filePath</code> we are just focusing on the file where we have our <code>JSON</code> data placed. So we are targeting the current working directory (cwd), then the <code>backendData</code> folder, and then the <code>JSON</code> file.</p>
<p>With <code>fileData</code> we are trying to read this file and extract the actual <code>JSON</code> data that is stored in it.</p>
<p>We need <code>data</code> to convert this <code>fileData</code> so we can actually use it for our next steps.</p>
<p>All in all, <code>getData()</code> basically just provides us with the data from the <code>some-backend-data.json</code> file so we can utilize it in <code>getStaticProps()</code> as well as in <code>getStaticPaths()</code>. There is not much more to it.</p>
<h3 id="heading-setup-for-getstaticprops">🔨 Setup for <code>getStaticProps()</code></h3>
<p>After we implement <code>getData()</code> (which will come in handy when we try to fetch our dummy backend data), we'll now create the <code>getStaticProps()</code> function next.</p>
<p>Here, we'll use <code>getStaticProps()</code> to enable pre-rendering for the specific fetched data for the paths in our dynamic route.</p>
<p>Before we jump right into the code example below, have a quick thought about what we actually want to accomplish. </p>
<p>The user should be directed to this specific dynamic route, which is indicated by a unique identifier in the URL. By that, I mean that we want <code>/test/St2-18</code> and <code>test/UY-SC</code> to lead to the same dynamic page. </p>
<p>The data that the user will see there should, however, differ from each other since we want to fetch data for <code>St2-18</code> and <code>UY-SC</code>, respectively.</p>
<p>We have a <code>getData()</code> function which helps reach out to our backend data. But we still have to know which exact data we want to extract from our dummy backend.</p>
<p>For this step, we can pull the specific identifier from the URL, <code>St2-18</code> for example, and combine this with our extracted <code>getData()</code> result data. </p>
<p>From there we can search for the specific object containing the data we want to display within our backend's <code>getData()</code> result.</p>
<p>Now, let's head back to our code example to see this process in action.</p>
<p>See the following code section where we implement <code>getStaticProps()</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getStaticProps: GetStaticProps = <span class="hljs-keyword">async</span> (context) =&gt; {
    <span class="hljs-keyword">const</span> itemID = context.params?.something;
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> getData();
    <span class="hljs-keyword">const</span> foundItem = data.stars.find(<span class="hljs-function">(<span class="hljs-params">item: starInterface</span>) =&gt;</span> itemID === item.id);

    <span class="hljs-keyword">if</span> (!foundItem) {
      <span class="hljs-keyword">return</span> {
        props: { hasError: <span class="hljs-literal">true</span> },
      }
  }

  <span class="hljs-keyword">return</span> {
    props: {
      specificStarData: foundItem
    }
  }
}
</code></pre>
<p>For JavaScript, you can just omit <code>GetStaticProps</code> as the type for <code>getStaticProps()</code>. </p>
<p><code>getStaticProps()</code> can provide us with a <code>context</code> parameter through which we can reach some helpful methods. For now, it's just important to understand that through <code>context</code> we are able to access <code>params</code> and then afterwards reach out to the current identifier of our specific path for which <code>something</code> is the placerholder. </p>
<p>Remember that this file is actually called <code>[something].tsx</code>, which is why we access <code>something</code> in this context.</p>
<p>With this approach, we successfully extract the information we need from our URL to search for the specific object in our backend data array. Then we save this information in the <code>itemID</code> variable.</p>
<p>Let's say the user reaches out to <code>/test/St2-18</code>, then <code>itemID</code> would hold the value of <code>St2-18</code>.</p>
<p>Since we have our handy <code>getData()</code> function, we can just get our backend data through this function and save it to <code>data</code>.</p>
<p>Since we now have <code>itemID</code> as well as <code>data</code>, we can combine both variables and create <code>foundItem</code>. This returns the object that includes the <code>itemID</code> as an <code>id</code>.</p>
<p>With the <code>if</code> statement, we are checking if <code>foundItem</code> actually exists. Or in other words, we check if our backend data contains data with the corresponding <code>id</code> we extracted through our <code>itemID</code>.</p>
<p>If no data can be found, we return this boolean <code>hasError</code> with the value <code>true</code>. This helps us manage such cases on the frontend.</p>
<p>If there is data, then we return our <code>foundItem</code> to the frontend. Keep in mind that everything you return in this <code>props</code> object will actually be exposed to the frontend. So don't return any credentials (personal API keys, for example).</p>
<h3 id="heading-setup-for-getstaticpaths">🔨 Setup for <code>getStaticPaths()</code></h3>
<p>Before we head to the frontend part of our dynamic page, we still need to implement the <code>getStaticPaths()</code> function:</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getStaticPaths: GetStaticPaths = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> getData();
    <span class="hljs-keyword">const</span> pathsWithParams = data.stars.map(<span class="hljs-function">(<span class="hljs-params">star: starInterface</span>) =&gt;</span> ({ params: { something: star.id }}))

    <span class="hljs-keyword">return</span> {
        paths: pathsWithParams,
        fallback: <span class="hljs-literal">true</span>
    }
  }
</code></pre>
<p>For JavaScript, you can just omit <code>GetStaticPaths</code> as the type for <code>getStaticPaths()</code>. You can also delete <code>starInterface</code> for JavaScript.</p>
<p>Within the <code>getStaticPaths()</code> function, we want to tell Next.js which paths should be pre-rendered. </p>
<p>For this step, we are accessing our backend data with <code>getData()</code>, as you saw in <code>getStaticProps()</code>.</p>
<p><code>getStaticPaths()</code> demands a specific form for the <code>paths</code> within the return. You actually have two options:</p>
<ul>
<li>The first one is the approach I am using in this example: <code>paths: [{ params: { something: star.id } }]</code>. It should be an array with an object for every path you want Next.js to pre-render.</li>
<li>The second option is to use path strings like this: <code>paths: ['/test/St2-18', '...', '...']</code>.</li>
</ul>
<p>Both techniques achieve the same behavior, so just pick the one you prefer.</p>
<h3 id="heading-what-is-the-fallback-property">What is the <code>fallback</code> property?</h3>
<p>It's important to understand is that you don't need to include every path which should be pre-rendered. This is especially helpful when you have a lot of cases to consider and don't want everything to be pre-rendered. </p>
<p>To handle such cases, the <code>fallback</code> property is particularly useful</p>
<p>You can read more about the <code>fallback</code> in detail in the <a target="_blank" href="https://nextjs.org/docs/api-reference/data-fetching/get-static-paths#fallback-false">official Next.js documentation</a>.</p>
<p>In my own words, I would explain it like this:</p>
<ul>
<li><code>fallback</code> set to <code>false</code> would automatically lead to a 404 error page whenever the user tried to access a path which wasn't recognized by <code>getStaticPaths()</code> through the paths property.</li>
<li><code>fallback</code> set to <code>true</code> doesn't automatically lead to a 404 error page whenever the user tries to access a path that doesn't exist in <code>getStaticPaths()</code>.
This way, we still reach out to the frontend and are able to handle the situation there by displaying some sort of loading sequence, for example. 
You can also display an error on the frontend if there wasn't any data to be fetched when there was no valid item data for the specific path parameter.</li>
<li><code>fallback</code> set to <code>'blocking'</code> doesn't automatically lead to a 404 error page whenever the user tries to access a path that doesn't exist in <code>getStaticPaths()</code>. 
It's similar to <code>fallback</code> set to <code>true</code> but now we basically omit any manual loading processes. Instead, the browser just takes a moment longer to fetch the data and then displays the page ready to go. 
This is helpful when you don't want to present a "Loading..." to the user, for example, and instead just let them wait a little longer before the page is loaded successfully. If no data could be found, then we still have the opportunity to create a manual error on the frontend.</li>
</ul>
<p>Since we have such a small dataset, we are just giving every possible path to <code>getStaticPaths()</code>. So we technically don't need too much attention to the <code>fallback</code> property. </p>
<p>Still, I am setting <code>fallback</code> to <code>true</code> to show you how you can handle such manual errors as well as loading sequences that might occur.</p>
<h3 id="heading-how-to-configure-the-frontend">📐 How to Configure the Frontend</h3>
<p>In the last step, we'll configure our actual page. Anything in here will be the frontend content that the user will see:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">projectPage</span>(<span class="hljs-params">props: { specificStarData: starInterface, 
hasError: <span class="hljs-built_in">boolean</span> }</span>) </span>{
  <span class="hljs-keyword">const</span> router = useRouter();

  <span class="hljs-keyword">if</span> (props.hasError) {
    <span class="hljs-keyword">return</span> &lt;h1&gt;<span class="hljs-built_in">Error</span> - please <span class="hljs-keyword">try</span> another parameter&lt;/h1&gt;
  }

  <span class="hljs-keyword">if</span> (router.isFallback) {
      <span class="hljs-keyword">return</span> &lt;h1&gt;Loading...&lt;/h1&gt;
  }

  <span class="hljs-keyword">return</span> (
    &lt;div&gt;
      &lt;h1&gt;{props.specificStarData.name}&lt;/h1&gt;
      &lt;p&gt;{props.specificStarData.description}&lt;/p&gt;
      &lt;a href={props.specificStarData.link}&gt;More Information here (link)&lt;/a&gt;
    &lt;/div&gt;
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> projectPage;
</code></pre>
<p>For JavaScript, you don't have to mention the <code>starInterface</code> as well as <code>boolean</code> within the function's arguments.</p>
<p>In the code above you can find our <code>specificStarData</code> as well as <code>hasError</code>, which both hold some values. Besides that, we utilize the <code>useRouter()</code> hook in order to have access to <code>isFallback</code>, which helps us handle any <code>fallback</code> cases. </p>
<p>Remember that the <code>fallback</code> from <code>getStaticPaths()</code> can be set to <code>true</code> or <code>'blocking'</code> if you are not able to provide every dynamic route for pre-loading. In these cases, it would prevent your page from crashing. </p>
<p>Instead, it will load for some time on the fly as the user accesses this specific dynamic route and then provides the respective information.</p>
<p>For this potential loading sequence, we use <code>router.isFallback</code> in order to return JSX with some sort of loading indication for the user.</p>
<p>If there actually is an error because the user tried to access a dynamic path for which no data can be found, <code>hasError</code> steps in, indicating that there is an actual error.</p>
<p>Assuming that the user actually reached a dynamic path for which data could be fetched, the actual intended JSX output will be returned.</p>
<p>Following all the configuration steps (with <code>fallback: true</code>), we receive this output for the <code>/test/St2-18</code> path:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/image-250.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result for <strong>/test/St2-18</strong></em></p>
<p>If we try to put in an invalid parameter, it first tries to load and then returns our manual set up error message:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/07/image-252.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result for <strong>/test/this-will-produce-an-error</strong></em></p>
<h3 id="heading-how-to-test-the-fallback-property">🎲 How to Test the <code>fallback</code> Property</h3>
<p>And that's pretty much it! The result is a dynamic route which uses <code>getStaticProps()</code> as well as <code>getStaticPaths()</code> in order to pre-render the fetched data from our dummy backend. </p>
<p>When you are working with <code>getStaticPaths()</code> for the first time, I recommend trying out the different <code>fallback</code> values (<code>true</code>, <code>false</code>, <code>'blocking'</code>) to find out how exactly your application's behavior changes.</p>
<p>Since we are using <code>fallback: true</code> in our example, we are also able to just insert one possible path out of the three without having our application crash. </p>
<p>So let's say we change the <code>paths</code> property within <code>getStaticPaths()</code> to <code>paths: ['/test/St2-18']</code>. While we inserted all the paths before, we now just use one path with the string method I mentioned earlier instead of the <code>{ params: { something: star.id }}</code> format. </p>
<p>With this configuration, you can still access <code>/test/UY-SC</code>, for example, but you'll notice that the <code>Loading...</code> message appears for a brief moment because we prepared this case in our if-statement with <code>router.isFallback</code>. After the data is loaded, it will successfully show up on the screen.</p>
<p>When using <code>fallback: 'blocking'</code> and <code>paths: ['/test/St2-18']</code>, you'll notice that you can't see any <code>Loading...</code>. Instead, the browser just takes a moment longer to load the data before changing the browser's content.</p>
<p>It's up to you which way you prefer.</p>
<h2 id="heading-conclusion"><strong>✅</strong> Conclusion</h2>
<p>While this example shows the fundamental parts of <code>getStaticProps()</code> as well <code>getStaticPaths()</code>, there is still more to read about these Next.js functions.</p>
<p>Still, all you've read here is enough to get started working with <code>getStaticProps()</code> and <code>getStaticPaths()</code> on your own in a lot of cases.</p>
<h2 id="heading-resources-amp-learning-material"><strong>📃</strong> Resources &amp; learning material</h2>
<ul>
<li>Official Next.js documentation for <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching/overview"><strong>Data Fetching</strong></a>.</li>
<li>For learning more about Next.js on the whole, I can strongly recommend checking out the <a target="_blank" href="https://www.udemy.com/course/nextjs-react-the-complete-guide/">udemy course by Maximilian Schwarzmüller for Next.js</a>. This course helped me a lot, at least.</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Routing in Next.js – A Complete Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ By Ibrahima Ndaw Next.js is a React framework that ships with all the features you need for production. It enables routing in your app by using the file-system-based routing.  In this guide, I will show you how routing works in Next.js. How Routing ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/routing-in-nextjs-beginners-guide/</link>
                <guid isPermaLink="false">66d8502cbfb3c4f0b376afe1</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 05 Oct 2020 17:12:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/cover-1--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ibrahima Ndaw</p>
<p>Next.js is a React framework that ships with all the features you need for production. It enables routing in your app by using the file-system-based routing. </p>
<p>In this guide, I will show you how routing works in Next.js.</p>
<ul>
<li><a class="post-section-overview" href="#heading-how-routing-works-in-nextjs">How Routing works in Next.js</a></li>
<li><a class="post-section-overview" href="#linking-between-pages">Linking between pages</a></li>
<li><a class="post-section-overview" href="#passing-route-parameters">Passing route parameters</a></li>
<li><a class="post-section-overview" href="#heading-dynamic-routes">Dynamic routes</a></li>
<li><a class="post-section-overview" href="#heading-dynamic-nested-routes">Dynamic nested routes</a></li>
</ul>
<h2 id="heading-how-routing-works-in-nextjs">How Routing works in Next.js</h2>
<p>Next.js uses the file system to enable routing in the app. Next automatically treats every file with the extensions <code>.js</code>, <code>.jsx</code>, <code>.ts</code>, or <code>.tsx</code> under the <code>pages</code> directory as a route. </p>
<p>A page in Next.js is a React component that has a route based on its file name.</p>
<p>Consider this folder structure as an example:</p>
<pre><code>├── pages
|  ├── index.js
|  ├── contact.js
|  └── my-folder
|     ├── about.js
|     └── index.js
</code></pre><p>Here, we have four pages:</p>
<ul>
<li><code>index.js</code> is the home page accessible on <a target="_blank" href="http://localhost:3000">http://localhost:3000</a></li>
<li><code>contact.js</code> is the contact page accessible on <a target="_blank" href="http://localhost:3000/contact">http://localhost:3000/contact</a></li>
<li><code>my-folder/index.js</code> is the page located on the sub-folder <em>my-folder</em> accessible on <a target="_blank" href="http://localhost:3000/my-folder">http://localhost:3000/my-folder</a></li>
<li><code>my-folder/about.js</code> is the about page located on the sub-folder <em>my-folder</em> accessible on <a target="_blank" href="http://localhost:3000/my-folder/about">http://localhost:3000/my-folder/about</a></li>
</ul>
<h2 id="heading-how-to-link-between-pages">How to link between pages</h2>
<p>By default, Next.js pre-renders every page to make your app fast and user-friendly. It uses the <code>Link</code> component provided by <em>next/link</em> to enable transitions between routes.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">"next/link"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">IndexPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>My second page<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/my-folder/about"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>My third page<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>Here, we have two routes:</p>
<ul>
<li>The first link leads to the page <code>http://localhost:3000/contact</code></li>
<li>The second link leads to the page <code>http://localhost:3000/my-folder/about</code></li>
</ul>
<p>The <code>Link</code> component can receive several properties, but only the <code>href</code> attribute is required. Here, we use a <code>&lt;a&gt;&lt;/a&gt;</code> tag as a child component to link pages. But alternatively you can use any element that supports the <code>onClick</code> event on the <code>Link</code> component.</p>
<h2 id="heading-how-to-pass-route-parameters">How to pass route parameters</h2>
<p>Next.js allows you to pass route parameters and then get back the data using the <code>useRouter</code> hook or <code>getInitialProps</code>. It gives you access to the router object that contains the params.</p>
<ul>
<li>index.js</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">"next/link"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">IndexPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Link</span>
      <span class="hljs-attr">href</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">pathname:</span> "/<span class="hljs-attr">about</span>",
        <span class="hljs-attr">query:</span> { <span class="hljs-attr">id:</span> "<span class="hljs-attr">test</span>" },
      }}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>About page<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span></span>
  )
}
</code></pre>
<p>As you can see here, instead of providing a string to the <code>href</code> attribute, we pass in an object that contains a <code>pathname</code> property. This is the route, along with a query element that holds the data.</p>
<ul>
<li>about.js</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AboutPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> router = useRouter()
  <span class="hljs-keyword">const</span> {
    <span class="hljs-attr">query</span>: { id },
  } = router
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>About us: {id}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>Here, we import the <code>useRouter</code> hook to get the data passed in. Next, we pull it from the <code>query</code> object using destructuring.</p>
<p>If you are using server-side rendering, you have to use <code>getInitialProps</code> to get the data.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AboutPage</span>(<span class="hljs-params">{ id }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>About us: {id}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}

AboutPage.getInitialProps = <span class="hljs-function">(<span class="hljs-params">{ query: { id } }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> { id }
}
</code></pre>
<h2 id="heading-dynamic-routes">Dynamic routes</h2>
<p>Next.js enables you to define dynamic routes in your app using the brackets (<code>[param]</code>). Instead of setting a static name on your pages, you can use a dynamic one.</p>
<p>Let's use this folder structure as an example:</p>
<pre><code>├── pages
|  ├── index.js
|  ├── [slug].js
|  └── my-folder
|     ├── [id].js
|     └── index.js
</code></pre><p>Next.js will get the route parameters passed in and then use it as a name for the route.</p>
<ul>
<li>index.js</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">IndexPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/[slug]"</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"/my-slug"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>First Route<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/my-folder/[id]"</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"/my-folder/my-id"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Second Route<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
  )
}
</code></pre>
<p>Here, we have to define the value on the <code>as</code> attribute because the path is dynamic. The name of the route will be whatever you set on the <code>as</code> prop.</p>
<ul>
<li>[slug].js</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DynamicPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> router = useRouter()
  <span class="hljs-keyword">const</span> {
    <span class="hljs-attr">query</span>: { id },
  } = router
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>The dynamic route is {id}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>You can get the route parameters as well with the <code>useRouter</code> hook on the client or <code>getInitialProps</code> on the server.</p>
<ul>
<li>my-folder/[id].js</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyDynamicPage</span>(<span class="hljs-params">{ example }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>My example is {example}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}

MyDynamicPage.getInitialProps = <span class="hljs-function">(<span class="hljs-params">{ query: { example } }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> { example }
}
</code></pre>
<p>Here, we use <code>getInitialProps</code> to get the dynamic route passed in.</p>
<h2 id="heading-dynamic-nested-routes">Dynamic nested routes</h2>
<p>With Next.js, you can also nest dynamic routes with the brackets (<code>[param]</code>).</p>
<p>Let's consider this file structure:</p>
<pre><code>├── pages
|  ├── index.js
|  └── [dynamic]
|     └── [id].js
</code></pre><ul>
<li>index.js</li>
</ul>
<pre><code class="lang-jsx"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">IndexPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/[dynamic]/[id]"</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"/my-folder/my-id"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Dynamic nested Route<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
  )
}
</code></pre>
<p>As you can see here, we set the dynamic values on the <code>as</code> attribute as we did in the previous example. But this time, we have to define the name of the folder and its file.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DynamicPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> router = useRouter()
  <span class="hljs-keyword">const</span> {
    <span class="hljs-attr">query</span>: { dynamic, id },
  } = router
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      Data: {dynamic} - {id}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>Here, we pull out the route parameters from the query object with the <code>useRouter</code> hook.</p>
<p>That's it! Thanks for reading.</p>
<p>If you're interested in learning Next.js in a comprehensive way, I highly recommend this <a target="_blank" href="https://click.linksynergy.com/deeplink?id=o1JCNdqL0gw&amp;mid=39197&amp;murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Freact-the-complete-guide-incl-redux%2F">bestseller course</a>.</p>
<p>You can find other great content like this on <a target="_blank" href="https://www.ibrahima-ndaw.com">my blog</a> or follow me <a target="_blank" href="https://twitter.com/ibrahima92_">on Twitter</a> to get notified.</p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@soymeraki?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Javier Allegue Barros</a> on <a target="_blank" href="https://unsplash.com/s/photos/route?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build a state-based router using React and MobX State Tree ]]>
                </title>
                <description>
                    <![CDATA[ By Miles Till Introducing mobx-state-tree-router _Image by [Flickr](https://www.flickr.com/photos/medithit/" rel="noopener" target="_blank" title="">medithIT on <a href="https://www.flickr.com/photos/medithit/10363854753/" rel="noopener" target="bla... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-state-based-router-using-react-and-mobx-state-tree-e91b2b8e8d79/</link>
                <guid isPermaLink="false">66c34ff79972b7c5c7624ec0</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 03 May 2019 17:31:11 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*IIwgT670HJ7Ni-_UDA3-Ow.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Miles Till</p>
<p><strong>Introducing <a target="_blank" href="https://github.com/miles-till/mobx-state-tree-router">mobx-state-tree-router</a></strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/q2nzV7mcMyhC5USDlGtwtCaFCkdhdaj93Q48" alt="Image" width="786" height="611" loading="lazy">
_Image by [Flickr](https://www.flickr.com/photos/medithit/" rel="noopener" target="_blank" title=""&gt;medithIT on &lt;a href="https://www.flickr.com/photos/medithit/10363854753/" rel="noopener" target="<em>blank" title=")</em></p>
<p><em>If you want to skip ahead to the finished example you can check it out at <a target="_blank" href="https://github.com/miles-till/mobx-state-tree-router-demo">mobx-state-tree-router-demo</a>.</em></p>
<p>I wrote a library that makes it easy to configure state-based routing in MobX State Tree powered React apps, and I want to share it with you. To do this I will demonstrate how to build a very simple Todo app.</p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-a-state-based-router-using-react-and-mobx-state-tree-e91b2b8e8d79/undefined">Michel Weststrate</a>, the creator of MobX, wrote a great article titled <a target="_blank" href="https://hackernoon.com/how-to-decouple-state-and-ui-a-k-a-you-dont-need-componentwillmount-cc90b787aa37">How to decouple state and UI (a.k.a. you don’t need componentWillMount)</a>. I recommend reading it to understand the philosophy that inspired me to write mobx-state-tree-router. The key idea is that the application UI should be a function of the state.</p>
<blockquote>
<p>“This approach has better decoupling of state and UI. This has a few advantages:</p>
<ol>
<li><p>The complete application flow can be tested without ever needing to instantiate a component.</p>
</li>
<li><p>More components can be dumb; they don’t have to fetch data or process routing.</p>
</li>
<li><p>Our stores become more like a state machine, making it easy to follow the transitions of our application.”</p>
</li>
<li><p>Michel Weststrate</p>
</li>
</ol>
</blockquote>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>These will need to be installed to follow this tutorial:</p>
<ul>
<li><a target="_blank" href="https://nodejs.org/en/">Node.js</a> — used for running the dev server</li>
<li><a target="_blank" href="https://yarnpkg.com/en/">Yarn</a> — used for package management</li>
</ul>
<p><em>Note: NPM can be used instead of Yarn but some commands may be different.</em></p>
<h3 id="heading-create-a-basic-react-app">Create a basic React app</h3>
<h4 id="heading-use-create-react-app-to-get-started-quickly">Use create-react-app to get started quickly</h4>
<p>If you haven’t used it before, the easiest way to get started with a React app is to use a scaffolding tool by the developers of React called <a target="_blank" href="https://github.com/facebook/create-react-app">Create React App</a>. This tool configures <a target="_blank" href="https://webpack.js.org/">Webpack</a> and <a target="_blank" href="https://babeljs.io/">Babel</a> for you with the most common requirements met.</p>
<p>In your terminal run the following commands:</p>
<pre><code>npx create-react-app state-router-democd state-router-demoyarn start
</code></pre><p>You will now have a fully functioning basic React app to play with.</p>
<h4 id="heading-remove-create-react-app-stuff-not-needed-for-this-example">Remove create-react-app stuff not needed for this example</h4>
<p>For the purposes of this tutorial we don’t need a lot of the stuff that create-react-app generates so go ahead and delete:</p>
<pre><code>src/App.csssrc/App.test.jssrc/index.csssrc/logo.svgsrc/serviceWorker.js
</code></pre><p><em>Note: Feel free to keep the css files and add your own styling.</em></p>
<p>To keep things organised, create a <code>components</code> directory in our <code>src</code> and move <code>src/App.js</code> to <code>src/components/App.js</code>.</p>
<p>Now update the following files to remove references to the files we deleted:</p>
<p><strong>src/components/App.js</strong></p>
<p><strong>src/index.js</strong></p>
<p>If you still have the app running you will notice your browser has updated to show you the following:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/HmmOo0FbypGJUW0fxqIAjxU-Vpv3ApchARCJ" alt="Image" width="800" height="210" loading="lazy"></p>
<h4 id="heading-create-a-home-page-component">Create a Home page component</h4>
<p>In the <code>components</code> directory, create a file for our Home page component:</p>
<p><strong>src/components/Home.js</strong></p>
<p>Update the App component to render our new Home page component:</p>
<p><strong>src/components/App.js</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NCx1sB4ZwpZrNUG4giyv6GWhjB1VQSf5cMMZ" alt="Image" width="800" height="222" loading="lazy"></p>
<h3 id="heading-add-mobx-state-tree-models">Add MobX State Tree models</h3>
<h4 id="heading-install-mobx-and-mobx-state-tree">Install MobX and MobX State Tree</h4>
<p><a target="_blank" href="https://github.com/mobxjs/mobx">MobX</a> is a library for state management, and it works great with React as our renderer. <a target="_blank" href="https://github.com/mobxjs/mobx-state-tree">MobX State Tree</a> is a tree shaped state container built on top of MobX.</p>
<p>In your terminal run:</p>
<pre><code>yarn add mobx mobx-react mobx-state-tree
</code></pre><p>Like our we did for our components, create a <code>models</code> directory to keep our MobX State Tree models organised.</p>
<h4 id="heading-create-a-rootstore-model">Create a RootStore model</h4>
<p>In our state tree we’ll have a <code>RootStore</code> which holds our data stores (in this case a <code>TodoStore</code>) and our <code>RouterStore</code>, but we’ll get to that later.</p>
<p><strong>src/models/RootStore.js</strong></p>
<h4 id="heading-create-todostore-and-todo-models">Create TodoStore and Todo models</h4>
<p>Our <code>TodoStore</code> contains <code>Todo</code> objects which are able to be created, removed, and updated. We also need to be able to find a <code>Todo</code> object by its <code>id</code>.</p>
<p><strong>src/models/TodoStore.js</strong></p>
<h4 id="heading-initialize-the-rootstore">Initialize the RootStore</h4>
<p>When our app loads, we want to initialize the <code>RootStore</code> with a known state. For this trivial example we won’t be concerned about persisting our data to storage in any way. We then want to make sure the <code>RootStore</code> is available to be injected into our components, so we use the MobX React component <code>Provider</code> to do this.</p>
<p><strong>src/index.js</strong></p>
<h4 id="heading-create-a-todolist-page-component">Create a TodoList page component</h4>
<p>Now that we have a <code>RootStore</code> for our state tree, we need some components to view and change the data.</p>
<p><strong>src/components/TodoList.js</strong></p>
<p>Update the <code>App</code> component to display our new <code>TodoList</code> component.</p>
<p><strong>src/components/App.js</strong></p>
<p>At this point the app should have a list of <code>Todo</code> objects which you can add to and remove from.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/R2JwZQj-xFt2LdACX-zYQHZtZVNtujhZn5Oj" alt="Image" width="800" height="393" loading="lazy"></p>
<h4 id="heading-create-a-todo-page-component">Create a Todo page component</h4>
<p>Now we want to create a new component to display and edit a <code>Todo</code> object. Note that we are using <code>inject</code> to make the <code>RootStore</code> available in the component’s props.</p>
<p><strong>src/components/Todo.js</strong></p>
<p>Update the <code>App</code> component to display our new <code>Todo</code> component.</p>
<p>Now our updated app allows us to edit the data of the <code>Todo</code> whose id we pass to the Todo page component in <code>&lt;Todo todoId={0}</code> /&gt;.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NMq1Crdl8b1XeXy-3L95whd2bp7j1VV7LnoN" alt="Image" width="800" height="292" loading="lazy"></p>
<h3 id="heading-add-state-based-routing">Add state-based routing</h3>
<p>At this point we should have a React app with our data stored in a MobX State Tree container. The data container is then being injected into the components that need access to the data. Now we want to connect together our page components in our app. A common approach would be to use a component based router such as <a target="_blank" href="https://github.com/ReactTraining/react-router">React Router</a>. Often the components become cluttered with route definitions and mount event handlers. This doesn’t suit our state-first philosophy.</p>
<p>I will now show you how to add mobx-state-tree-router to your app.</p>
<h4 id="heading-install-mobx-state-tree-router">Install mobx-state-tree-router</h4>
<p>In your terminal run:</p>
<pre><code>yarn add mobx-state-tree-router
</code></pre><h4 id="heading-add-the-router-to-the-rootstore">Add the router to the RootStore</h4>
<p><strong>src/models/RootStore.js</strong></p>
<h4 id="heading-create-views">Create views</h4>
<p>The router needs to be configured with a map of view models which define the route paths to match against and the page components to display. Hooks into the page change cycle can be defined on a view to perform data fetching, route change cancelling, redirection, and other tasks. These hooks can be synchronous or asynchronous.</p>
<p>These hooks are:</p>
<ul>
<li><code>beforeExit(self, params)</code></li>
<li><code>beforeEnter(self, params)</code></li>
<li><code>onExit(self, params)</code></li>
<li><code>onEnter(self, params)</code></li>
</ul>
<p>If either of the before hooks return <code>false</code> the route change will be cancelled.</p>
<p>Create a <code>views</code> file:</p>
<p><strong>src/views.js</strong></p>
<h4 id="heading-initialize-the-router-when-our-app-starts">Initialize the router when our app starts</h4>
<p>The router can be started by calling <code>startRouter(router)</code>. This function connects the router to the browser’s history and configures the routing based on router’s views.</p>
<p><strong>src/index.js</strong></p>
<h4 id="heading-render-the-staterouter">Render the StateRouter</h4>
<p>Update the <code>App</code> component to include the <code>StateRouter</code> component, which renders the appropriate component for the router’s current view.</p>
<p><strong>src/components/App.js</strong></p>
<p>Now our app will respond to changes in the url path, for example <code>/todos</code> will show our <code>TodoList</code> component and <code>/todos/0</code> will show our <code>Todo</code> component as configured in <code>views.js</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OAPfHYOwTqQ494DZyUiiC3th5XHaP8ffaC9w" alt="Image" width="800" height="365" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/K3rVKI18B-2Belhpaqe2B1r4EoMMHEFFx5pG" alt="Image" width="800" height="307" loading="lazy"></p>
<h4 id="heading-add-navigation-links">Add navigation links</h4>
<p>Currently our app doesn’t have any way to navigate around other than changing the url directly. This doesn’t work particularly well in this simple example as the data in our <code>RootStore</code> will get reset to the initial state as defined in <code>index.js</code> every time the page loads.</p>
<p>There are 2 other ways to change the route using mobx-state-tree-router:</p>
<ul>
<li><code>Link</code> components</li>
<li>Calling <code>router.setView(view, params)</code> directly</li>
</ul>
<p>I recommend using <code>Link</code> components where possible, but in some cases (like redirects) setting the view directly may be unavoidable. Let’s update our <code>App</code> and <code>TodoList</code> components to add some navigation links using both methods:</p>
<p><strong>src/components/App.js</strong></p>
<p><strong>src/components/TodoList.js</strong></p>
<p>You will now be able to add a <code>Todo</code> item on the <code>todos</code> view, then click the open button to go the <code>todo</code> view for the new item:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/8eH6t6vmnyuG3xWb0zVME9Rg7-d4VKj2GouY" alt="Image" width="800" height="364" loading="lazy"></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>I created mobx-state-tree-router because I found that there was a gap in the landscape for a state-based routing library to use with MobX State Tree. I have found it to be useful for me, so I hope it can also be useful to the wider community.</p>
<p>If you haven’t already please read <a target="_blank" href="https://hackernoon.com/how-to-decouple-state-and-ui-a-k-a-you-dont-need-componentwillmount-cc90b787aa37">Michel Weststrate’s article</a> for some background on state-based routing.</p>
<p>If you have any issues to raise or contributions to make, please head over to <a target="_blank" href="https://github.com/miles-till/mobx-state-tree-router">mobx-state-tree-router on Github</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Really, really basic routing in Node.js with Express ]]>
                </title>
                <description>
                    <![CDATA[ By Pau Pavón The goal of this story is to briefly explain how routing works in Express while building a simple — very simple — Node app. We’ll also use EJS, a template engine that “lets you generate HTML markup with plain JavaScript,” according to th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/really-really-basic-routing-in-nodejs-with-express-d7cad5e3f5d5/</link>
                <guid isPermaLink="false">66c35da539357f9446976611</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ routing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 03 Apr 2018 04:19:40 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*FWsvE-8X-T1wNDj5." medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Pau Pavón</p>
<p>The goal of this story is to briefly explain how routing works in Express while building a simple — very simple — Node app.</p>
<p>We’ll also use EJS, a template engine that “lets you generate HTML markup with plain JavaScript,” according to <a target="_blank" href="http://ejs.co/">their website</a>. Basically, it’ll let us create HTML pages that can vary depending on the request the client makes. We won’t be using this last feature, but it’s a great one. At the end of this article, you’ll find some resources where you can learn more.</p>
<h3 id="heading-what-is-routing-in-2-ish-lines">What is routing? (In 2-ish lines)</h3>
<p>First of all, let’s take a quick (really quick) glance at what routing is:</p>
<blockquote>
<p>somewebsite.com/someroute</p>
</blockquote>
<p>It’s basically taking the user (or some data) from one place to another. That place is the route. I told you I was going to make it quick.</p>
<h3 id="heading-creating-the-project">Creating the project</h3>
<p>We’re going to build a fancy website to learn how routing works in Express. Check it out:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/zKy5qHElo1OJCfcnBBlTS0rU2RqIvIaPPHRc" alt="Image" width="800" height="415" loading="lazy"></p>
<p>Cool, right? But it’s everything we need for the moment.</p>
<p>First, let’s create the project and install the packages. Just run the following in the command line:</p>
<blockquote>
<p>npm install express</p>
<p>npm install ejs</p>
</blockquote>
<p>You can additionally add the <em>dash dash save</em> (I write — as “<em>dash”</em> because Medium automatically formats it, and it doesn’t look well for this purpose) to save it in your <em>package.json</em> file. But how this works is a story for another day.</p>
<p>Then we will require Express and set the view engine to EJS in our <em>app.js</em> file as follows:</p>
<pre><code><span class="hljs-keyword">var</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);<span class="hljs-keyword">var</span> app = express();app.set(<span class="hljs-string">'view engine'</span>, <span class="hljs-string">'ejs'</span>);
</code></pre><p>We’ll also include the following line so our app listens for requests:</p>
<pre><code>app.listen(<span class="hljs-number">3000</span>);
</code></pre><h3 id="heading-handling-get-requests">Handling GET requests</h3>
<p>Congratulations, everything is ready to handle requests! There are several types of requests in HTTP, but we’ll only be handling GET requests, which are used to retrieve data from the server. To handle this kind of request in Express, we use the following method:</p>
<pre><code>app.get(<span class="hljs-string">'/about'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>{  res.render(<span class="hljs-string">'about'</span>);});
</code></pre><p>Let’s take a look at what’s happening here. We’re telling our server that, whenever someone types in <em>somewebsite.com/about</em>, we want to fire a function. That function takes two parameters, <em>req</em> (request) and <em>res</em> (response). Using the response object, we render the <em>about page</em>.</p>
<p>For this to work, we’ll have to create a page named <em>about.ejs</em> in HTML. We’ll also place it in a folder called <em>views</em> inside our project folder. This is the folder where Express will look to render the view. Here you have the mega-complex about page we’ll be using for this example:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xHlH6J5GdxC1m8GhzCNtf5WRI71Lv-QEUYgt" alt="Image" width="800" height="414" loading="lazy"></p>
<p>Nice! But, what if the user doesn’t type in any route? Just like we do most of the times, <em>somewebsite.com</em>? Well, really easy. Change <em>/about</em> to just <em>/,</em> and render whatever page you like:</p>
<pre><code>app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>{  res.render(<span class="hljs-string">'home'</span>);});
</code></pre><h3 id="heading-handling-non-existing-routes">Handling non-existing routes</h3>
<p>But what if someone types in a route that doesn’t exist? We probably don’t want a default error page to show up. Instead, we want a custom, cool error page.</p>
<p>Well, the good news is that it’s extremely easy to make one with Express. Just replace the route parameter in the get method with an asterisk and render your own error page like so:</p>
<pre><code>app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>{  res.render(<span class="hljs-string">'error'</span>);});
</code></pre><h3 id="heading-trying-it-out">Trying it out!</h3>
<p>Finally, let’s run our server from the command line (assuming the server is named <em>app.js</em>)</p>
<blockquote>
<p>node app</p>
</blockquote>
<p>and see if it works! Let’s type in the name of our server (<em>localhost</em>, as it’s a local server running on our computer) and the port (<em>3000</em> in this case) in our browser:</p>
<blockquote>
<p>localhost:3000</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1KFP8uvz25ry2d2pNQ2QsSdQnacvlqM3E2ex" alt="Image" width="800" height="415" loading="lazy">
<em>localhost:3000 or localhost:3000/</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/eDCDZV5wyUWUoLFsLQQnZU5hHa9P8rgxDirO" alt="Image" width="800" height="414" loading="lazy">
<em>localhost:3000/about</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hkwkh0YVUHuY-0LWm6zUmlMXUXYrr2P6hSZj" alt="Image" width="800" height="414" loading="lazy">
<em>localhost:3000/anythingthatwehaventsetaroutefor</em></p>
<p>Amazing!</p>
<h3 id="heading-further-reading">Further reading</h3>
<p>You can learn everything you need to know about routing in the <a target="_blank" href="http://expressjs.com/en/guide/routing.html">Express guide</a>, and there’s a lot of handy things in the <a target="_blank" href="http://ejs.co">EJS website</a> as well!</p>
<p>I hope this article was helpful for you. If it was, please leave a comment and clap it up!</p>
<p>Happy coding… <strong><em>Or happy routing, I guess!</em></strong></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
