Uploading Images to Firebase
In this article, I am specifically going to address the issue of Uploading the Images to the Firebase Storage and then Displaying them to the Front-End using React.
Before you jump into reading the passage further, it's highly recommended to first take a look at "Authentication using Firebase" as this is connected to the Authentication of User.
Flow of Project
--> User Registration
--> User Login
--> Displaying User Profile --> Uploading Image to Firebase Storage
--> Displaing Images as soon as they are uploaded
Firebase Setup
Go to the Firebase console and select the existing project which you created earlier. Check "Authentication using Firebase" for reference.
Select Storage option in the sidebar and click on Get Started.
Go to the "Rules" tab and paste the following rules:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/{userId}/{allPaths=**} {
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
- Click on Publish button.
Coding starts here
Jump to "profile.jsx" inside your existing project directory.
Make the following changes to your code:
/* eslint-disable no-unused-vars */
import React, { useEffect, useState } from 'react';
import { Link, Navigate } from 'react-router-dom';
import { auth, firestore, storage } from '../../firebase';
import { collection, doc, getDoc } from 'firebase/firestore';
import { ref, uploadBytes, listAll, getDownloadURL } from 'firebase/storage';
import { v4 as uuidv4 } from "uuid";
import './Profile.css';
function Profile() {
const [fullName, setFullName] = useState('');
const [isLoading, setLoading] = useState(true);
const [imageUpload, setImageUpload] = useState(null);
const [imageList, setImageList] = useState([]);
// For displaying UserName
useEffect(() => {
const fetchUserData = async () => {
try {
const user = auth.currentUser;
if (user) {
const userDocRef = doc(collection(firestore, 'users'), user.uid);
const userDocSnapshot = await getDoc(userDocRef);
if (userDocSnapshot.exists()) {
const userData = userDocSnapshot.data();
setFullName(userData.fullName);
}
}
} catch (error) {
console.error(error);
}
setLoading(false);
};
fetchUserData();
}, []);
// For fetching and displaying Images
useEffect(() => {
const fetchImages = async () => {
try {
const user = auth.currentUser;
if (user) {
const userId = user.uid;
const imageListRef = ref(storage, `images/${userId}/`);
const response = await listAll(imageListRef);
const urls = await Promise.all(
response.items.map(async (item) => {
const downloadURL = await getDownloadURL(item);
return downloadURL;
})
);
setImageList(urls);
}
} catch (error) {
console.error(error);
}
};
fetchImages();
}, []);
const uploadImage = () => {
if (imageUpload == null) return;
const user = auth.currentUser;
if (user) {
const userId = user.uid;
const imageRef = ref(storage, `images/${userId}/${imageUpload.name}_${uuidv4()}`);
uploadBytes(imageRef, imageUpload)
.then(() => {
alert("Image uploaded successfully");
// Fetch and update the image list after successful upload
fetchImages();
})
.catch((error) => {
console.error(error);
});
}
};
const fetchImages = async () => {
try {
const user = auth.currentUser;
if (user) {
const userId = user.uid;
const imageListRef = ref(storage, `images/${userId}/`);
const response = await listAll(imageListRef);
const urls = await Promise.all(
response.items.map(async (item) => {
const downloadURL = await getDownloadURL(item);
return downloadURL;
})
);
setImageList(urls);
}
} catch (error) {
console.error(error);
}
};
if (isLoading) {
return <p>Loading...</p>;
}
if (!auth.currentUser) {
return <Navigate to="/login" />;
}
return (
<>
<div className="container">
<div className="form-container">
<h2>Welcome, {fullName}!</h2>
<br />
<p>This is your profile page.</p>
<br />
<p>
Go back to <Link to="/login">Login</Link> page.
</p>
</div>
</div>
<div className="container">
<div className='input-container'>
<input
type="file"
onChange={(event) => {
setImageUpload(event.target.files[0]);
}}
/>
<button onClick={uploadImage}>Upload</button>
</div>
</div>
<div className='images'>
{imageList.map((url) => {
return <img key={url} src={url} alt='img' />;
})}
</div>
</>
);
}
export default Profile;
The first
useEffect
fetches the user's data from Firestore and updates thefullName
state.The second
useEffect
fetches the list of images for the user from Firebase Storage and updates theimageList
state.The
uploadImage
function handles the image upload process and updates the image list after a successful upload.The
fetchImages
function fetches the list of images for the user from Firebase Storage.Another
useEffect
hook listens for changes in the authentication state and redirects to the login page if the user is not authenticated.
Inside your Firebase.js, add the following statement in the Header section:
import { getStorage } from "firebase/storage";
Add this code at the last:
const storage = getStorage(app);
export { app, auth, firestore, storage };
That's it!! You have successfully implemented User Authentication using Firebase which provides a profile page where Authenticated users can Upload and View images.
Project Snippets
Conclusion
You have successfully made a Project using Firebase and React JS which provides a profile page where Authenticated users can Upload and View images.
In case you are facing any difficulties or to get the full source code of this project, simply DM me on my LinkedIn.