How to Upload Files in React JS

As a developer, I was working on a React project where I needed to allow users to upload images and documents to the application. As simple as this sounds, implementing file uploads in React can be tricky if you don’t understand the fundamentals.

In this article, I’ll walk you through multiple approaches to implementing file uploads in React JS, from basic implementations to more advanced solutions using popular libraries.

So let’s get in!

Upload Files in React JS

Now, I will explain the methods to upload files in React JS.

Method 1: Basic File Upload Using React State

Let’s start with the simplest approach, using React’s state to handle a single file upload.

import React, { useState } from 'react';

function BasicFileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [isFilePicked, setIsFilePicked] = useState(false);
  const [isUploading, setIsUploading] = useState(false);

  const changeHandler = (event) => {
    setSelectedFile(event.target.files[0]);
    setIsFilePicked(true);
  };

  const handleSubmission = async () => {
    if (!selectedFile) return;

    setIsUploading(true);

    const formData = new FormData();
    formData.append('file', selectedFile);

    try {
      const response = await fetch('https://your-api-endpoint.com/upload', {
        method: 'POST',
        body: formData,
      });

      const result = await response.json();
      console.log('Success:', result);
      // Handle success - maybe show a success message
    } catch (error) {
      console.error('Error:', error);
      // Handle error - show error message
    } finally {
      setIsUploading(false);
    }
  };

  return (
    <div>
      <h2>Upload a File</h2>
      <input type="file" name="file" onChange={changeHandler} />

      {isFilePicked ? (
        <div>
          <p>Filename: {selectedFile.name}</p>
          <p>Filetype: {selectedFile.type}</p>
          <p>Size in bytes: {selectedFile.size}</p>
        </div>
      ) : (
        <p>Select a file to show details</p>
      )}

      <div>
        <button onClick={handleSubmission} disabled={!isFilePicked || isUploading}>
          {isUploading ? 'Uploading...' : 'Submit'}
        </button>
      </div>
    </div>
  );
}

export default BasicFileUpload;

I executed the above example code and added the screenshot below.

Upload Files in React JS

This basic implementation allows users to:

  1. Select a file using the file input
  2. See details about the selected file
  3. Upload the file to a server endpoint

Method 2: Multiple File Uploads in React

Often, you’ll need to allow users to upload multiple files at once. Here’s how to modify our example to handle multiple file uploads:

import React, { useState } from 'react';

function MultipleFileUpload() {
  const [selectedFiles, setSelectedFiles] = useState([]);
  const [isUploading, setIsUploading] = useState(false);

  const changeHandler = (event) => {
    setSelectedFiles(Array.from(event.target.files));
  };

  const handleSubmission = async () => {
    if (selectedFiles.length === 0) return;

    setIsUploading(true);

    const formData = new FormData();
    selectedFiles.forEach((file, index) => {
      formData.append(`file${index}`, file);
    });

    try {
      const response = await fetch('https://your-api-endpoint.com/upload-multiple', {
        method: 'POST',
        body: formData,
      });

      const result = await response.json();
      console.log('Success:', result);
      // Handle success
    } catch (error) {
      console.error('Error:', error);
      // Handle error
    } finally {
      setIsUploading(false);
    }
  };

  return (
    <div>
      <h2>Upload Multiple Files</h2>
      <input type="file" name="files" onChange={changeHandler} multiple />

      {selectedFiles.length > 0 ? (
        <div>
          <p>Files selected: {selectedFiles.length}</p>
          <ul>
            {selectedFiles.map((file, index) => (
              <li key={index}>
                {file.name} - {file.size} bytes
              </li>
            ))}
          </ul>
        </div>
      ) : (
        <p>Select files to upload</p>
      )}

      <div>
        <button 
          onClick={handleSubmission} 
          disabled={selectedFiles.length === 0 || isUploading}
        >
          {isUploading ? 'Uploading...' : 'Submit'}
        </button>
      </div>
    </div>
  );
}

export default MultipleFileUpload;

I executed the above example code and added the screenshot below.

How to Upload Files in React JS

The key differences here are:

  • Adding the multiple attribute to the file input
  • Handling an array of files instead of a single file
  • Appending multiple files to the FormData object

Method 3: Drag and Drop File Upload

A more user-friendly approach is to implement drag-and-drop functionality. Here’s how to create a drag-and-drop file upload component:

import React, { useState, useRef } from 'react';
import './DragDropUpload.css'; // You'll need to create this CSS file

function DragDropUpload() {
  const [files, setFiles] = useState([]);
  const [isDragging, setIsDragging] = useState(false);
  const fileInputRef = useRef(null);

  const handleDragOver = (e) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(true);
  };

  const handleDragLeave = (e) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
  };

  const handleDrop = (e) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);

    const droppedFiles = Array.from(e.dataTransfer.files);
    setFiles(prevFiles => [...prevFiles, ...droppedFiles]);
  };

  const handleFileSelect = (e) => {
    const selectedFiles = Array.from(e.target.files);
    setFiles(prevFiles => [...prevFiles, ...selectedFiles]);
  };

  const removeFile = (index) => {
    setFiles(files.filter((_, i) => i !== index));
  };

  const uploadFiles = async () => {
    if (files.length === 0) return;

    const formData = new FormData();
    files.forEach((file, index) => {
      formData.append(`file${index}`, file);
    });

    try {
      const response = await fetch('https://your-api-endpoint.com/upload-multiple', {
        method: 'POST',
        body: formData,
      });

      const result = await response.json();
      console.log('Success:', result);
      setFiles([]);
      // Show success message
    } catch (error) {
      console.error('Error:', error);
      // Show error message
    }
  };

  return (
    <div className="upload-container">
      <div 
        className={`drop-zone ${isDragging ? 'active' : ''}`}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
        onClick={() => fileInputRef.current.click()}
      >
        <p>Drag and drop files here or click to select files</p>
        <input 
          type="file" 
          multiple 
          onChange={handleFileSelect} 
          ref={fileInputRef}
          style={{ display: 'none' }}
        />
      </div>

      {files.length > 0 && (
        <div className="file-list">
          <h3>Selected Files:</h3>
          <ul>
            {files.map((file, index) => (
              <li key={index}>
                {file.name}
                <button onClick={() => removeFile(index)}>Remove</button>
              </li>
            ))}
          </ul>
          <button onClick={uploadFiles}>Upload All Files</button>
        </div>
      )}
    </div>
  );
}

export default DragDropUpload;

For this to work properly, you’ll need some CSS. Here’s a simple example for DragDropUpload.css:

.upload-container {
  max-width: 800px;
  margin: 0 auto;
}

.drop-zone {
  border: 2px dashed #ccc;
  border-radius: 4px;
  padding: 40px;
  text-align: center;
  cursor: pointer;
  transition: border 0.3s ease;
}

.drop-zone.active {
  border-color: #007bff;
  background-color: #f8f9fa;
}

.file-list {
  margin-top: 20px;
}

.file-list ul {
  list-style: none;
  padding: 0;
}

.file-list li {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #eee;
}

button {
  padding: 8px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #0069d9;
}

button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

I executed the above example code and added the screenshot below.

Upload Drag and Drop Files in React JS

Method 4: Use React Dropzone Library

Instead of building drag-and-drop functionality from scratch, you can use the popular React-Dropzone library:

import React, { useState, useCallback } from 'react';
import { useDropzone } from 'react-dropzone';

function ReactDropzoneUpload() {
  const [files, setFiles] = useState([]);
  const [uploading, setUploading] = useState(false);

  const onDrop = useCallback(acceptedFiles => {
    setFiles(prevFiles => [...prevFiles, ...acceptedFiles]);
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({ 
    onDrop,
    accept: {
      'image/*': ['.jpeg', '.jpg', '.png'],
      'application/pdf': ['.pdf']
    }
  });

  const removeFile = (index) => {
    setFiles(files.filter((_, i) => i !== index));
  };

  const uploadFiles = async () => {
    if (files.length === 0) return;
    
    setUploading(true);
    const formData = new FormData();
    files.forEach((file, index) => {
      formData.append(`file${index}`, file);
    });
    
    try {
      const response = await fetch('https://your-api-endpoint.com/upload', {
        method: 'POST',
        body: formData,
      });
      
      const result = await response.json();
      console.log('Success:', result);
      setFiles([]);
      / Show success message
    } catch (error) {
      console.error('Error:', error);
      // Show error message
    } finally {
      setUploading(false);
    }
  };

  return (
    <div className="upload-container">
      <div 
        {...getRootProps()} 
        className={`dropzone ${isDragActive ? 'active' : ''}`}
      >
        <input {...getInputProps()} />
        {isDragActive ? (
          <p>Drop the files here...</p>
        ) : (
          <p>Drag & drop some files here, or click to select files</p>
        )}
      </div>
      
      {files.length > 0 && (
        <div className="file-list">
          <h3>Selected Files:</h3>
          <ul>
            {files.map((file, index) => (
              <li key={index}>
                {file.name} - {(file.size / 1024).toFixed(2)} KB
                <button onClick={() => removeFile(index)}>Remove</button>
              </li>
            ))}
          </ul>
          <button onClick={uploadFiles} disabled={uploading}>
            {uploading ? 'Uploading...' : 'Upload All Files'}
          </button>
        </div>
      )}
    </div>
  );
}

export default ReactDropzoneUpload;

The react-dropzone library makes it much easier to implement drag-and-drop file uploads with features like:

  • File type validation
  • Size limits
  • Multiple file handling
  • Preview generation

Method 5: Upload Files with Progress Tracking

When uploading large files, it’s helpful to show users a progress indicator. We can use the XMLHttpRequest object to track upload progress:

import React, { useState } from 'react';

function ProgressFileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploading, setUploading] = useState(false);

  const handleFileChange = (event) => {
    setSelectedFile(event.target.files[0]);
    setUploadProgress(0);
  };

  const uploadFile = () => {
    if (!selectedFile) return;
    
    setUploading(true);
    
    const formData = new FormData();
    formData.append('file', selectedFile);
    
    // Use XMLHttpRequest for progress tracking
    const xhr = new XMLHttpRequest();
    
    xhr.upload.addEventListener('progress', (event) => {
      if (event.lengthComputable) {
        const percentComplete = Math.round((event.loaded / event.total) * 100);
        setUploadProgress(percentComplete);
      }
    });
    
    xhr.addEventListener('load', () => {
      if (xhr.status === 200) {
        console.log('Upload complete');
        // Show success message
      } else {
        console.error('Upload failed');
        // Show error message
      }
      setUploading(false);
    });
    
    xhr.addEventListener('error', () => {
      console.error('Upload failed');
      // Show error message
      setUploading(false);
    });
    
    xhr.open('POST', 'https://your-api-endpoint.com/upload', true);
    xhr.send(formData);
  };

  return (
    <div className="upload-container">
      <h2>Upload with Progress</h2>
      <input type="file" onChange={handleFileChange} />
      
      {selectedFile && (
        <div className="file-details">
          <p>File: {selectedFile.name}</p>
          <p>Size: {(selectedFile.size / 1024 / 1024).toFixed(2)} MB</p>
        </div>
      )}
      
      {uploading && (
        <div className="progress-container">
          <div 
            className="progress-bar" 
            style={{ width: `${uploadProgress}%` }}
          >
            {uploadProgress}%
          </div>
        </div>
      )}
      
      <button 
        onClick={uploadFile} 
        disabled={!selectedFile || uploading}
      >
        {uploading ? 'Uploading...' : 'Upload File'}
      </button>
    </div>
  );
}

export default ProgressFileUpload;

You’ll need some CSS for the progress bar:

.progress-container {
  width: 100%;
  height: 20px;
  background-color: #e0e0e0;
  border-radius: 4px;
  margin: 10px 0;
}

.progress-bar {
  height: 100%;
  background-color: #4caf50;
  border-radius: 4px;
  text-align: center;
  color: white;
  transition: width 0.3s ease;
}

Method 6: Use Axios for File Uploads

Axios provides a cleaner API for handling HTTP requests, including file uploads with progress tracking:

import React, { useState } from 'react';
import axios from 'axios';

function AxiosFileUpload() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploading, setUploading] = useState(false);

  const handleFileChange = (event) => {
    setSelectedFile(event.target.files[0]);
    setUploadProgress(0);
  };

  const uploadFile = async () => {
    if (!selectedFile) return;
    
    setUploading(true);
    
    const formData = new FormData();
    formData.append('file', selectedFile);
    
    try {
      await axios.post('https://your-api-endpoint.com/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          setUploadProgress(percentCompleted);
        }
      });
      
      console.log('Upload successful');
      // Show success message
    } catch (error) {
      console.error('Error uploading file:', error);
      // Show error message
    } finally {
      setUploading(false);
    }
  };

  return (
    <div className="upload-container">
      <h2>Upload with Axios</h2>
      <input type="file" onChange={handleFileChange} />
      
      {selectedFile && (
        <div className="file-details">
          <p>File: {selectedFile.name}</p>
          <p>Size: {(selectedFile.size / 1024 / 1024).toFixed(2)} MB</p>
        </div>
      )}
      
      {uploading && (
        <div className="progress-container">
          <div 
            className="progress-bar" 
            style={{ width: `${uploadProgress}%` }}
          >
            {uploadProgress}%
          </div>
        </div>
      )}
      
      <button 
        onClick={uploadFile} 
        disabled={!selectedFile || uploading}
      >
        {uploading ? 'Uploading...' : 'Upload File'}
      </button>
    </div>
  );
}

export default AxiosFileUpload;

Method 7: Create a Reusable File Upload Hook

To make our code more reusable, let’s create a custom React hook for file uploads:

// useFileUpload.js
import { useState } from 'react';
import axios from 'axios';

export function useFileUpload() {
  const [files, setFiles] = useState([]);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState(null);
  const [success, setSuccess] = useState(false);

  const handleFileChange = (event) => {
    const newFiles = Array.from(event.target.files);
    setFiles(newFiles);
    setUploadProgress(0);
    setError(null);
    setSuccess(false);
  };

  const uploadFiles = async (url) => {
    if (files.length === 0) return;
    
    setUploading(true);
    setError(null);
    setSuccess(false);
    
    const formData = new FormData();
    files.forEach((file, index) => {
      formData.append(`file${index}`, file);
    });
    
    try {
      const response = await axios.post(url, formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          setUploadProgress(percentCompleted);
        }
      });
      
      setSuccess(true);
      return response.data;
    } catch (err) {
      setError(err.message || 'An error occurred during upload');
      throw err;
    } finally {
      setUploading(false);
    }
  };

  const clearFiles = () => {
    setFiles([]);
    setUploadProgress(0);
    setError(null);
    setSuccess(false);
  };

  return {
    files,
    uploadProgress,
    uploading,
    error,
    success,
    handleFileChange,
    uploadFiles,
    clearFiles
  };
}

Now we can use this hook in any component:

import React from 'react';
import { useFileUpload } from './useFileUpload';

function FileUploadComponent() {
  const {
    files,
    uploadProgress,
    uploading,
    error,
    success,
    handleFileChange,
    uploadFiles,
    clearFiles
  } = useFileUpload();

  const handleUpload = async () => {
    try {
      await uploadFiles('https://your-api-endpoint.com/upload');
      // Handle successful upload
    } catch (err) {
      // Error is already handled in the hook
      console.log('Upload failed');
    }
  };

  return (
    <div className="upload-container">
      <h2>File Upload</h2>
      <input 
        type="file" 
        multiple 
        onChange={handleFileChange} 
        disabled={uploading}
      />
      
      {files.length > 0 && (
        <div className="file-list">
          <h3>Selected Files:</h3>
          <ul>
            {files.map((file, index) => (
              <li key={index}>
                {file.name} - {(file.size / 1024).toFixed(2)} KB
              </li>
            ))}
          </ul>
        </div>
      )}
      
      {uploading && (
        <div className="progress-container">
          <div 
            className="progress-bar" 
            style={{ width: `${uploadProgress}%` }}
          >
            {uploadProgress}%
          </div>
        </div>
      )}
      
      {error && <div className="error-message">{error}</div>}
      {success && <div className="success-message">Files uploaded successfully!</div>}
      
      <div className="button-group">
        <button 
          onClick={handleUpload} 
          disabled={files.length === 0 || uploading}
          Clear Files
    </button>
  </div>
</div>
);
}

export default FileUploadComponent;

## Handling Image Preview Before Upload

When uploading images, it's often helpful to show a preview before the actual upload. Here's how to implement this:

```jsx
import React, { useState } from 'react';

function ImageUploadWithPreview() {
  const [selectedImage, setSelectedImage] = useState(null);
  const [preview, setPreview] = useState(null);

  const handleImageChange = (event) => {
    const file = event.target.files[0];
    
    if (file) {
      setSelectedImage(file);
      
      // Create a preview URL for the image
      const reader = new FileReader();
      reader.onloadend = () => {
        setPreview(reader.result);
      };
      reader.readAsDataURL(file);
    }
  };

  const uploadImage = async () => {
    if (!selectedImage) return;
    
    const formData = new FormData();
    formData.append('image', selectedImage);
    
    try {
      const response = await fetch('https://your-api-endpoint.com/upload-image', {
        method: 'POST',
        body: formData,
      });
      
      const result = await response.json();
      console.log('Success:', result);
      // Handle success
    } catch (error) {
      console.error('Error:', error);
      // Handle error
    }
  };

  return (
    <div className="image-upload-container">
      <h2>Upload Image with Preview</h2>
      <input 
        type="file" 
        accept="image/*" 
        onChange={handleImageChange} 
      />
      
      {preview && (
        <div className="image-preview">
          <h3>Preview:</h3>
          <img 
            src={preview} 
            alt="Preview" 
            style={{ maxWidth: '300px', maxHeight: '300px' }} 
          />
        </div>
      )}
      
      <button 
        onClick={uploadImage} 
        disabled={!selectedImage}
      >
        Upload Image
      </button>
    </div>
  );
}

export default ImageUploadWithPreview;

Read State in React JS

Build a Complete File Upload Component

Now, let’s build a more complete file upload component that combines many of the features we’ve covered:

import React, { useState, useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
import axios from 'axios';
import './CompleteFileUpload.css';

function CompleteFileUpload() {
  const [files, setFiles] = useState([]);
  const [uploading, setUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState({});
  const [successfulUploads, setSuccessfulUploads] = useState([]);
  const [error, setError] = useState(null);

  const onDrop = useCallback(acceptedFiles => {
    // Add preview URLs for images
    const newFiles = acceptedFiles.map(file => Object.assign(file, {
      preview: file.type.startsWith('image/') 
        ? URL.createObjectURL(file) 
        : null,
      id: Math.random().toString(36).substring(2)
    }));
    
    setFiles(prevFiles => [...prevFiles, ...newFiles]);
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({ 
    onDrop,
    accept: {
      'image/*': ['.jpeg', '.jpg', '.png', '.gif'],
      'application/pdf': ['.pdf'],
      'application/msword': ['.doc'],
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'],
      'text/plain': ['.txt']
    },
    maxSize: 10485760 // 10MB
  });

  const removeFile = (id) => {
    setFiles(files.filter(file => file.id !== id));
  };

  const uploadFiles = async () => {
    if (files.length === 0) return;
    
    setUploading(true);
    setError(null);
    
    // Initialize progress for each file
    const progressObj = {};
    files.forEach(file => {
      progressObj[file.id] = 0;
    });
    setUploadProgress(progressObj);
    
    const successful = [];
    
    for (const file of files) {
      const formData = new FormData();
      formData.append('file', file);
      
      try {
        const response = await axios.post('https://your-api-endpoint.com/upload', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          },
          onUploadProgress: (progressEvent) => {
            const percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            setUploadProgress(prev => ({
              ...prev,
              [file.id]: percentCompleted
            }));
          }
        });
        
        successful.push(file.id);
      } catch (err) {
        setError(`Error uploading ${file.name}: ${err.message}`);
        break;
      }
    }
    
    setSuccessfulUploads(successful);
    setUploading(false);
    
    // Remove successfully uploaded files
    if (successful.length > 0) {
      setFiles(files.filter(file => !successful.includes(file.id)));
    }
  };

  // File type icon function
  const getFileIcon = (file) => {
    if (file.type.startsWith('image/')) {
      return '🖼️';
    } else if (file.type.includes('pdf')) {
      return '📄';
    } else if (file.type.includes('word')) {
      return '📝';
    } else if (file.type.includes('text')) {
      return '📃';
    } else {
      return '📁';
    }
  };

  return (
    <div className="complete-upload-container">
      <h2>File Upload Center</h2>
      
      <div 
        {...getRootProps()} 
        className={`complete-dropzone ${isDragActive ? 'active' : ''}`}
      >
        <input {...getInputProps()} />
        {isDragActive ? (
          <p>Drop the files here...</p>
        ) : (
          <div>
            <p>Drag & drop files here, or click to select files</p>
            <p className="upload-note">
              Supported formats: Images, PDF, DOC, DOCX, TXT (Max: 10MB per file)
            </p>
          </div>
        )}
      </div>
      
      {error && <div className="upload-error">{error}</div>}
      
      {successfulUploads.length > 0 && (
        <div className="upload-success">
          Successfully uploaded {successfulUploads.length} file(s)!
        </div>
      )}
      
      {files.length > 0 && (
        <div className="file-list-container">
          <h3>Selected Files:</h3>
          <ul className="file-list">
            {files.map(file => (
              <li key={file.id} className="file-item">
                <div className="file-info">
                  {file.preview ? (
                    <img 
                      src={file.preview} 
                      alt="Preview" 
                      className="file-preview" 
                    />
                  ) : (
                    <span className="file-icon">{getFileIcon(file)}</span>
                  )}
                  <div className="file-details">
                    <span className="file-name">{file.name}</span>
                    <span className="file-size">{(file.size / 1024).toFixed(2)} KB</span>
                  </div>
                </div>
                
                {uploading && uploadProgress[file.id] !== undefined ? (
                  <div className="file-progress">
                    <div 
                      className="progress-bar" 
                      style={{ width: `${uploadProgress[file.id]}%` }}
                    >
                      {uploadProgress[file.id]}%
                    </div>
                  </div>
                ) : (
                  <button 
                    className="remove-file" 
                    onClick={() => removeFile(file.id)}
                    disabled={uploading}
                  >
                    ✕
                  </button>
                )}
              </li>
            ))}
          </ul>
          
          <div className="upload-actions">
            <button 
              className="upload-button"
              onClick={uploadFiles} 
              disabled={files.length === 0 || uploading}
            >
              {uploading ? 'Uploading...' : `Upload ${files.length} File${files.length !== 1 ? 's' : ''}`}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

export default CompleteFileUpload;

Best Practices for File Uploads in React

When implementing file uploads in your React applications, keep these best practices in mind:

  1. Validate files on the client side – Check file types, sizes, and other constraints before uploading to save bandwidth and server resources.
  2. Show progress indicators – For large files, always show upload progress to provide feedback to users.
  3. Handle errors gracefully – Display meaningful error messages when uploads fail.
  4. Limit file sizes – Set reasonable file size limits to prevent server overload.
  5. Provide visual feedback – Show previews for images and status indicators for all uploads.
  6. Implement chunked uploads for very large files** – For files over 100MB, consider implementing chunked uploads to improve reliability.
  7. Add retry functionality – Allow users to retry failed uploads.
  8. Security considerations – Always validate files on the server side as well, as client-side validation can be bypassed.

Read How to Reset Form in React JS

Conclusion

In this tutorial, I’ve covered multiple approaches to implementing file uploads in React JS – from basic implementations to more advanced solutions with drag-and-drop, progress tracking, and preview functionality.

Remember that file upload functionality often requires both client-side and server-side implementation. The examples I’ve shown focus on the React (client-side) part of the equation.

Related tutorials:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.