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:
- First, place your loading GIF file in the public or src/assets folder of your React project.
- 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;
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:
- 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;
- Make sure you have a loading GIF image in your project’s public folder or import it directly into your component.
- 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;
Custom Loading Hook
useGitHubUser
Hook: Manages GitHub API calls, handling loading and error states.Loading
Component: Displays a loading GIF from GIPHY.GitHubUser
Component: Renders GitHub user information.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>
);
}