DEV Community

Cover image for Next.js Image File Upload and Preview with shadcn/ui
Aaronn
Aaronn

Posted on • Originally published at frontendshape.com

Next.js Image File Upload and Preview with shadcn/ui

In this tutorial, we'll create an image file upload with a preview using Next.js and Shadcn UI.

In this guide, we will create a file upload feature in Next.js using React hooks. We will include a file preview using the Next.js Image component and utilize Shadcn UI's Input and Label components for file selection.

"use client"

import { useState } from "react"
import Image from "next/image"

import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

export default function InputFile() {
  const [selectedFile, setSelectedFile] = useState(null)

  const handleFileChange = (e) => {
    const file = e.target.files[0]
    if (file) {
      const reader = new FileReader()
      reader.onloadend = () => {
        setSelectedFile(reader.result)
      }
      reader.readAsDataURL(file)
    }
  }

  return (
    <div className="grid w-full max-w-sm items-center gap-1.5">
      <Label htmlFor="picture">Picture</Label>
      <Input id="picture" type="file" onChange={handleFileChange} />
      {selectedFile && (
        <div className="mt-2">
          <Image
            src={selectedFile}
            alt="Preview"
            className="rounded-md"
            width={500}
            height={500}
          />
        </div>
      )}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

image file upload and preview
Building a Next.js Image File Upload and Preview Feature Using TypeScript and Shadcn UI.

"use client"

import React, { ChangeEvent, useState } from 'react';
import Image from 'next/image'
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

interface InputFileProps {
  // You can add any additional props needed
}

export default function InputFile(props: InputFileProps) {
  const [selectedFile, setSelectedFile] = useState<string | null>(null);

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];

    if (file) {
      const reader = new FileReader();
      reader.onloadend = () => {
        setSelectedFile(reader.result as string);
      };
      reader.readAsDataURL(file);
    }
  };

  return (
    <div className="grid w-full max-w-sm items-center gap-1.5">
      <Label htmlFor="picture">Picture</Label>
      <Input id="picture" type="file" onChange={handleFileChange} />
      {selectedFile && (
        <div className="mt-2">
          <Image
            src={selectedFile}
            alt="Preview"
            width={500}
            height={500}
          />
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Next.js with Shadcn UI Image File Upload Preview and remove button for the image preview.

"use client"

import React, { ChangeEvent, useState } from 'react';
import Image from 'next/image'
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

interface InputFileProps {
  // You can add any additional props needed
}

export default function InputFile(props: InputFileProps) {
  const [selectedFile, setSelectedFile] = useState<string | null>(null);

  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];

    if (file) {
      const reader = new FileReader();
      reader.onloadend = () => {
        setSelectedFile(reader.result as string);
      };
      reader.readAsDataURL(file);
    }
  };

  const handleRemoveClick = () => {
    setSelectedFile(null);
  };

  return (
    <div className="grid w-full max-w-sm items-center gap-1.5">
      <Label htmlFor="picture">Picture</Label>
      <Input id="picture" type="file" onChange={handleFileChange} />
      {selectedFile && (
        <div className="mt-2 relative">
          <Image
            src={selectedFile}
            alt="Preview"
            width={500}
            height={500}
          />
          <button
            onClick={handleRemoveClick}
            className="absolute top-0 right-0 bg-red-500 text-white py-1 px-2"
            aria-label="Remove image"
          >
            X
          </button>
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

File Upload Preview and remove button

Top comments (0)