How to Implement Image Upload Functionality in React JS?

How to Implement Image Upload Functionality in React JS?

Here is complete code –

DeshProfile.jsx:

import React, { useEffect, useRef, useState } from ‘react’
import { Alert, Button, TextInput } from ‘flowbite-react’
import {useSelector} from ‘react-redux’
import {app} from ‘../firebase’
import {getDownloadURL, getStorage, ref, uploadBytesResumable} from ‘firebase/storage’
import { CircularProgressbar } from ‘react-circular-progressbar’;
import ‘react-circular-progressbar/dist/styles.css’;
const DashProfile = () => {
  const {currentUser}=useSelector(state=>state.user)
  const [imageFile, setImageFile]=useState(null)
  const [imageFileUrl, setImageFileUrl]=useState(null);
  const [imageFileUploadProgress, setImageFileUploadProgress]=useState(null);
  const [imageFileUploadError, setImageFileUploadError]=useState(null);
  console.log(imageFileUploadProgress, imageFileUploadError);
  const filePickerRef=useRef();
  const handleImageChange=(e)=>{
    const file=e.target.files[0];
    if(file){
     setImageFile(file);
    setImageFileUrl(URL.createObjectURL(file));
    }
  };
  useEffect(()=>{
    if(imageFile){
      uploadImage();
    }
  }, [imageFile])
  const uploadImage=async()=>{
    // service firebase.storage {
    //   match /b/{bucket}/o {
    //     match /{allPaths=**} {
    //       allow read;
    //       allow write: if
    //       request.resource.size<2*1024*1024 &&
    //       request.resource.contentType.matches(‘image/.*’);
    //     }
    //   }
    // }
    setImageFileUploadError(null)
    const storage=getStorage(app);
    const fileName=new Date().getTime()+imageFile.name;
    const storageRef=ref(storage, fileName);
    const uploadTask=uploadBytesResumable(storageRef, imageFile);
    uploadTask.on(
      ‘state_changed’,
      (snapshot)=>{
        const progress=(snapshot.bytesTransferred/snapshot.totalBytes)*100;
        setImageFileUploadProgress(progress.toFixed(0));
      },
      (error)=>{
        setImageFileUploadError(‘Could Not Upload Image (File must be less than 2MB)’)
        setImageFileUploadProgress(null)
        setImageFile(null);
        setImageFileUrl(null)
      },
      ()=>{
        getDownloadURL(uploadTask.snapshot.ref).then((downloadURL)=>{
          setImageFileUrl(downloadURL)
        })
      }
    )
    console.log(“Uploading Image…”)
  }
  console.log(imageFile, imageFileUrl)
  return (
    <div className=‘ max-w-lg mx-auto p-3 w-full’>
      <h1 className=‘my-7 text-center font-semibold text-3xl’>Profile</h1>
      <form className=‘flex flex-col gap-4’>
        <input type=‘file’ accept=‘image/*’ onChange={handleImageChange} ref={filePickerRef}/>
        <div className=‘ relative w-32 h-32 self-center cursor-pointer rounded-full shadow-md overflow-hidden’ onClick={()=>filePickerRef.current.click()}>
          {
            imageFileUploadProgress && (
              <CircularProgressbar value={imageFileUploadProgress || 0} text={`${imageFileUploadProgress}%`} strokeWidth={5} styles={{
                root:{
                  width:‘100%’,
                  height:‘100%’,
                  position:‘absolute’,
                  top:0,
                  left:0
                },
                path:{
                  stroke:`rgba(62, 152, 199, ${imageFileUploadProgress/100})`
                }
              }}/>
            )
          }
          <img src={imageFileUrl || currentUser.profilePicture} alt=‘user’ className={` rounded-full w-full h-full object-cover border-8 border-[lightgray] ${imageFileUploadProgress && imageFileUploadProgress<100 && ‘opacity-60’}`}/>
        </div>
        {
          imageFileUploadError && <Alert color=‘failure’>{imageFileUploadError}</Alert>
        }
        <TextInput type=‘text’ id=‘username’ placeholder=‘username’ defaultValue={currentUser.username}/>
        <TextInput type=’email’ id=’email’ placeholder=’email’ defaultValue={currentUser.email}/>
        <TextInput type=‘password’ id=‘password’ placeholder=‘password’/>
        <Button type=‘submit’ gradientDuoTone=‘purpleToBlue’ outline>Update</Button>
      </form>
      <div className=‘ text-red-500 flex justify-between gap-5’>
        <span className=‘ cursor-pointer’>Delete Account</span>
        <span className=‘ cursor-pointer’>Sign Out</span>
      </div>
    </div>
  )
}
export default DashProfile
 

Video Tutorial: