DEV Community

SWAPNIL AHMMED SHISHIR
SWAPNIL AHMMED SHISHIR

Posted on

How to Fix Image Preview and Display Issues in a React Gallery (with File Uploads)

When building a gallery or content management system in React, it's common to allow users to upload images and preview them before saving. However, you may run into a scenario where:

  • Images already stored in your database are displayed with URLs like /uploads/filename.jpg.
  • Newly selected images (not yet uploaded) are previewed using blob: URLs from URL.createObjectURL(file).
  • The preview works, but after saving, your gallery doesn’t display the images properly, or the paths are inconsistent.

This article walks you through a robust solution for handling both types of images—so your gallery works seamlessly for both existing and newly uploaded files.


The Problem

  • Uploaded images: When previewing a new file, React shows a blob: URL. This is fine for local preview, but this URL is not valid after you reload or fetch from the server.
  • Database images: When you fetch images from the backend, you get paths like /uploads/my-photo.jpg (or just uploads/my-photo.jpg). These need to be shown using the full backend URL.
  • When you render your gallery, you need to handle both cases in your preview and display logic.

The Solution Strategy

  1. For files already in the database:

    • Store only the relative path (e.g., uploads/my-photo.jpg) in your database.
    • When rendering, prepend your backend host (e.g., https://your-backend.com/ or http://localhost:5001/) to the path.
  2. For new images (before upload):

    • Use URL.createObjectURL(file) to generate a temporary preview.
    • These URLs start with blob: and should be used as-is.
  3. In your React component:

    • Create a helper function that checks if the image source is a blob: or a server path.
    • If it’s a server path, prepend your API URL. If it’s a blob, use it directly.

Example Implementation

const API = import.meta.env.VITE_OPEN_APIURL; // Your backend URL

// Helper function to get the correct image URL for preview
function getImageSrc(src) {
  if (!src) return "";
  if (src.startsWith("blob:")) return src; // New file preview
  // Remove starting slash if present
  const cleanSrc = src.replace(/^(\/+)/, "");
  // If already absolute (e.g., https://), return as is
  if (/^https?:\/\//.test(src)) return src;
  return `${API}/${cleanSrc}`; // Database images
}
Enter fullscreen mode Exit fullscreen mode

Usage in Your Component

// Example galleryImgs state
const [galleryImgs, setGalleryImgs] = useState([
  // Existing image from DB
  { src: "uploads/image1.jpg", file: null, isOld: true },
  // New image being previewed
  { src: "blob:http://localhost:5173/abc-123", file: FileObj, isOld: false }
]);

// Rendering
<div className="flex flex-wrap gap-4 mt-4">
  {galleryImgs.map((img, idx) => (
    <img
      key={idx}
      src={getImageSrc(img.src)}
      alt=""
      className="w-24 h-24 object-cover rounded-2xl"
    />
  ))}
</div>
Enter fullscreen mode Exit fullscreen mode

Additional Tips

  • Always store relative paths (like uploads/my-photo.jpg) in your database, not absolute URLs.
  • Use your backend’s host URL as a constant in your frontend, and prepend it for image display.
  • Clean paths that start with a slash, so you don't end up with double slashes in the URL.
  • Clean up blob URLs using URL.revokeObjectURL() when the image is removed from the preview to avoid memory leaks.

Conclusion

With this approach, your React gallery will correctly preview both newly added images and those already stored in your database, providing a smooth and professional user experience.

Always handle image URLs carefully, and your gallery will look great and work perfectly—no matter how your users interact with it!

Top comments (0)