How to Add a Loading GIF in ReactJS

When building dynamic web applications with ReactJS, displaying a loading indicator is crucial for enhancing user experience during data fetching or heavy computations. In this blog post, we will guide you through the simple steps to add a loading GIF in your ReactJS project, ensuring your users are always informed of ongoing processes.

To add a loading GIF in a React application, you can follow these steps:

  1. First, place your loading GIF file in the public or src/assets folder of your React project.
  2. Create a component for the loading spinner:
import React from 'react';

const LoadingSpinner = () => {
  return (
    <div className="loading-spinner">
      <img src="/path/to/your/loading.gif" alt="Loading..." />
    </div>
  );
};

export default LoadingSpinner;

Use the component in your main application or specific components where loading states are needed:

import { useState, useEffect } from 'react';
import LoadingSpinner from '../components/LoadingSpinner';

const Demo = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState(null);

  useEffect(() => {
    // Simulating an API call
    setTimeout(() => {
      setData("Your data");
      setIsLoading(false);
    }, 2000);
  }, []);

  if (isLoading) {
    return <LoadingSpinner />;
  }

  return (
    <div>
      {/* Your component content */}
      {data}
    </div>
  );
};

export default Demo;
loading gif

Conditional Rendering within a Component

To add a loading GIF in a React application while fetching data from an API, you can use state to manage the loading status. Here’s an example using the GitHub API to fetch user data:

  1. First, create a new React component:
import React, { useState, useEffect } from 'react';

function GitHubUser() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchUser();
  }, []);

  const fetchUser = async () => {
    try {
      const response = await fetch('https://api.github.com/users/fabpot');
      const data = await response.json();
      setUser(data);
      setLoading(false);
    } catch (error) {
      console.error('Error fetching user:', error);
      setLoading(false);
    }
  };

  if (loading) {
    return <img src="giphy.gif" alt="Loading..." />;
  }

  return (
    <div>
      {user && (
        <>
          <h2>{user.name}</h2>
          <img src={user.avatar_url} alt={user.login} width="100" />
          <p>Followers: {user.followers}</p>
          <p>Public Repos: {user.public_repos}</p>
        </>
      )}
    </div>
  );
}

export default GitHubUser;
  1. Make sure you have a loading GIF image in your project’s public folder or import it directly into your component.
  2. Use this component in your main App or another parent component:
import React from 'react';
import GitHubUser from './GitHubUser';

function App() {
  return (
    <div className="App">
      <h1>GitHub User Info</h1>
      <GitHubUser />
    </div>
  );
}

export default App;
Conditional Rendering gif loading

Custom Loading Hook

  1. useGitHubUser Hook: Manages GitHub API calls, handling loading and error states.
  2. Loading Component: Displays a loading GIF from GIPHY.
  3. GitHubUser Component: Renders GitHub user information.
  4. App Component: Allows input of a GitHub username and fetches user data.
import React, { useState, useEffect } from 'react';

// Custom Hook: useGitHubUser
function useGitHubUser(username) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchUser() {
      try {
        setLoading(true);
        const response = await fetch(`https://api.github.com/users/${username}`);
        if (!response.ok) {
          throw new Error('Failed to fetch user data');
        }
        const data = await response.json();
        setUser(data);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    }

    fetchUser();
  }, [username]);

  return { user, loading, error };
}

// Loading Component
function Loading() {
  return (
    <div className="loading">
      <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" alt="Loading..." />
    </div>
  );
}

// GitHubUser Component
function GitHubUser({ username }) {
  const { user, loading, error } = useGitHubUser(username);

  if (loading) {
    return <Loading />;
  }

  if (error) {
    return <div className="error">Error: {error}</div>;
  }

  return (
    <div className="user-info">
      {user && (
        <>
          <h2>{user.name}</h2>
          <img src={user.avatar_url} alt={user.login} width="100" />
          <p>Username: {user.login}</p>
          <p>Followers: {user.followers}</p>
          <p>Public Repos: {user.public_repos}</p>
          <p>Bio: {user.bio}</p>
        </>
      )}
    </div>
  );
}

// App Component
export default function App() {
  const [username, setUsername] = useState('octocat');
  const [inputUsername, setInputUsername] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    setUsername(inputUsername);
  };

  return (
    <div className="App">
      <h1>GitHub User Info</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={inputUsername}
          onChange={(e) => setInputUsername(e.target.value)}
          placeholder="Enter GitHub username"
        />
        <button type="submit">Fetch User</button>
      </form>
      <GitHubUser username={username} />
    </div>
  );
}
Custom Loading Hook
    Aaronn
    Aaronn

    Hey there! I'm Aaronn, a Full Stack Developer who's all about React, NEXTJS, Node.js, and Tailwind CSS. I'm on a mission to craft awesome websites that look great and work even better.