DEV Community

Cover image for Optimizing Usability and SEO with Loaders
Giovanni Lima
Giovanni Lima

Posted on ā€¢ Edited on

Optimizing Usability and SEO with Loaders

In web development, user experience is fundamental for creating fast and performative applications. These days, applications handle a ton of data that needs to be consumed and presented effectively. This can create a lot of problems on the front-end, so we need to find ways to handle these data efficiently without harming our apps. As our application grows, we need to be faster and more effective to ensure that the user experience remains good

In the context of ReactJS applications, optimizing SEO metrics is one of the most important factors for improving the visibility and engagement of our site

We recognize that applications using Next.js with Server-Side Rendering (SSR) can resolve many of these SEO issues. However, what about Single-Page Applications (SPAs)? Tools like react-router-dom, along with loaders, can help by ensuring that content is loaded efficiently, providing a better user experience and assisting
search engines in crawling and indexing dynamic content more effectively. This can be particularly useful in SPAs, where content is often loaded dynamically, and loaders can help manage the loading state to improve both user engagement and SEO metrics

What are Loaders in react-router-dom ?

React Router v6.4 introduced a key feature that improves how data is fetched and rendered in applications. This version allows us to fetch data in real-time before rendering the UI, based on specific routes.

Recently at work, I had to handle data from an API that was crucial for my page, both for enhancing the user experience by providing this data on the first render and for SEO metrics.

Let's Code!

To get started, we will set up the routes for our application using Vite. Let's create a file called router.tsx. This file will be responsible for defining all the routes of the application. We will use createBrowserRouter

// router.tsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Home from "./pages/Home";
import Products from "./pages/products";
import Contact from "./pages/Contact";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
  },
  {
    path: "/products",
    element: <Products />,
  },
  {
    path: "/contact",
    element: <Contact />,
  },
]);

export default router;
Enter fullscreen mode Exit fullscreen mode

Rendering Router

To render the router, we will need to use the RouterProvider component in the main file app.tsx.

// App.tsx
import React from "react";
import { RouterProvider } from "react-router-dom";
import router from "./router";

function App() {
  return <RouterProvider router={router} />;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Pratical Example: Route configuration with Loaders

Think of a situation where you are developing an application that displays product information. You want the data for a specific product to be available on the screen as soon as the user accesses its page, enhancing the user experience and facilitating search engine indexing. This method can help improve this scenario.

// router.tsx
import { createBrowserRouter } from "react-router-dom";
import Home from "./pages/Home";
import Products from "./pages/Products";
import Contact from "./pages/Contact";

const productsLoader = async () => {
  const response = await fetch('/api/products');  
  const productsData = await response.json();
  return productsData;
};

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
  },
  {
    path: "/products",
    element: <Products />,
    loader: productsLoader,
  },
  {
    path: "/contact",
    element: <Contact />,
  },
]);

export default router;
Enter fullscreen mode Exit fullscreen mode

By doing so, we can consume our API route directly within the loader, which allows us to fetch data before rendering the component.

Consuming data in component Products ā†©ļø

To use the data loaded by the loader in our Products component, we will use the useLoaderData hook.

import React from "react";
import { useLoaderData } from "react-router-dom";

function Products() {
  const productsData = useLoaderData();

  return (
    <div>
      <h1>Produtos</h1>
      <ul>
        {productsData.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default Products;
Enter fullscreen mode Exit fullscreen mode

This way, we can fetch data in React Router using data loaders. This is simple, right? This improves not only the user experience of viewing data on the screen but also helps with app indexing. Additionally, we can also work with scripts being inserted into the page before rendering. This solved a real problem we were having in the project, where scripts were loaded after the first render

Important Note šŸ”“

The loader should not be used in every scenario. It's crucial to evaluate based on your application and context so that it can be used in the best possible way.

Conclusion

I hope you enjoyed this article. If you have any feedback or notice any errors, please feel free to share in the comments. ā¤ļø

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more