Improve UX of React App with 'loader' function in React Router

Improve UX of React App with 'loader' function in React Router

Hey everyone I welcome you all again to my another tutorial where we will be learning about how we can improve the User Experience in our React apps.

Think! how do you deal with incoming data currently in React, say the data has to fetched from an external API. What we do is create a function to call the API and then call it inside the useEffect hook so that whenever the page reloads/refreshes the data is fetched and stored in a state. We then map over it and display it in the UI.

What if I tell you all this can be done in just few lines of code eliminating the use of useEffect and useState hooks?

Yes! In react-router v6 onward we have the 'loader' function which enables us to achieve the same.

Why 'loader' and not 'useEffect'?

In useEffect hook the function or the logic inside the useEffect fires only when the page is rendered, if the data is coming from an external API there is a white page in front of the user, which is a poor UX. Yes, we can add a loading animation until the data is received.

But what if the user has some content in front of them while the next page is getting ready? Loader function exactly does this for us.

Loader function gets the data ready to be displayed on the page before the page is rendered. In this way the user has the current page in front of them until the next page is rendered, improving the UX. In case of any failure it also provides a way to show an error page.

How to use 'loader' functions?

After defining your routes, open the file where you want to implement the loader function, for example let's say that you I want to implement loader function in component name Dashboard. So my Dashboard.jsx would look something like:

import React from 'react';

export async function loader() {
    const data = await fetch('/api/data');
    return data;
}

export default function Dashboard() {
    // Rest of the code...
}
  • First you need to define a loader function in the component where you want to fetch the data. As shown above

  • Once you have defined the loader function you need to attach it to it's respective route. This can be done by passing a prop to the <Route /> named 'loader'. Now as soon as the path name matches the route the loader function will be triggered and the data will be available to the page.

  • Suppose the routes are defined inside App.jsx

      import Dashboard, { loader as dashboardLoader } from '@/components/Dashboard';
    
      // The route will look like
      <Route 
          path='dashboard'
          element={<Dashboard />}
          loader={dashboardLoader}
      />
    
  • In case any error occurs, you don't have to handle it manually, you can just show your own custom error page. How cool is that! This can be done using the errorElement prop.

      import Dashboard, { loader as dashboardLoader } from '@/components/Dashboard';
    
      // The route will look like
      <Route 
          path='dashboard'
          element={<Dashboard />}
          loader={dashboardLoader}
          errorElement={<ErrorPage />}
      />
    
  • Now to access the data returned by loader function, we use the useLoaderData hook in the component where we have defined the loader function.

      import React from 'react';
      import useLoaderData from 'react-router-dom'
    
      export async function loader() {
          const data = await fetch('/api/data');
          return data;
      }
    
      export default function Dashboard() {
          const loaderData = useLoaderData();
          // Rest of the code...
      }
    

    That's a wrap. Try loader function in your next React Project and share it on socials and tag me! You can follow me X, I keep sharing valuable developer related stuff there!