Blog>
Snippets

Lazy Loading with Custom Hooks for Reusability

Create a custom React hook that implements lazy loading logic for components or data, promoting code reusability across the Next.js app.
import { useState, useEffect } from 'react';

export const useLazyLoad = (fetchFunction, dependants = []) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);
    fetchFunction()
      .then((response) => setData(response))
      .catch((error) => setError(error))
      .finally(() => setLoading(false));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, dependants);

  return { data, loading, error };
};
This custom hook, `useLazyLoad`, encapsulates the logic required to perform lazy loading of data or components. It takes a `fetchFunction` that returns a Promise, and an optional array of `dependants` which the effect depends on. The hook returns the current state of the data, a loading flag, and an error object, allowing the consuming component to respond to these states.
import React from 'react';
import { useLazyLoad } from './path-to-your-useLazyLoad-hook';

const MyComponent = () => {
  // Replace fetchData with your own data fetching function.
  const { data, loading, error } = useLazyLoad(fetchData);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!data) return null;

  // Render your component with the loaded data
  return (
    <div>{data.someAttribute}</div>
  );
};

export default MyComponent;
This example uses the `useLazyLoad` hook within a functional React component. You need to replace `fetchData` with the actual data fetching function that returns a Promise. While the data is loading, it renders a loading message. If there's an error, it displays the error message. Once the data is successfully fetched, it renders the component with the required data attributes.