React MUI 5 Image Upload with React-Hook-Form

In this tutorial, we’ll see image file upload in React Material UI 5 with the help of react-hook-form. Ensure you have React MUI 5 and react-hook-form installed and configured before getting started.

React MUI 5 Image Upload With React Hook Form

1. Create Image File Upload with Icon in React MUI 5 using useForm and Controller from react-hook-form.

import { useForm, Controller } from 'react-hook-form';
import { Button, TextField } from '@mui/material';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';

const ImageUpload = () => {
  const { control, handleSubmit } = useForm();

  const onSubmit = data => {
    // Handle the form data
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="image"
        control={control}
        defaultValue=""
        render={({ field }) => (
          <TextField
            {...field}
            type="file"
            InputLabelProps={{ shrink: true }}
            variant="outlined"
            fullWidth
            margin="normal"
          />
        )}
      />
      <Button
        variant="contained"
        color="primary"
        startIcon={<CloudUploadIcon />}
        type="submit"
      >
        Upload
      </Button>
    </form>
  );
};

export default ImageUpload;
react-hook-form image upload

2. React MUI 5 Image File Upload Form Validation using react-hook-form and TypeScript.

import React from 'react';
import { useForm, Controller, SubmitHandler } from 'react-hook-form';
import { Button, TextField } from '@mui/material';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';

// Define a type for the form data
type FormData = {
  image: FileList;
};

const ImageUpload: React.FC = () => {
  const { control, handleSubmit, formState: { errors } } = useForm<FormData>();

  const onSubmit: SubmitHandler<FormData> = data => {
    // Handle the form data
    console.log(data);
  };

  // Validation rule for image files
  const imageValidation = {
    required: 'An image file is required',
    validate: (fileList: FileList) => {
      if (fileList.length === 0) {
        return 'An image file is required';
      }
      const file = fileList[0];
      const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml'];
      if (!allowedTypes.includes(file.type)) {
        return 'Invalid file type. Please select an image (jpeg, png, gif, svg).';
      }
      return true;
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="image"
        control={control}
        rules={imageValidation}
        defaultValue=""
        render={({ field }) => (
          <TextField
            {...field}
            type="file"
            InputLabelProps={{ shrink: true }}
            variant="outlined"
            fullWidth
            margin="normal"
            error={!!errors.image}
            helperText={errors.image ? errors.image.message : ''}
          />
        )}
      />
      <Button
        variant="contained"
        color="primary"
        startIcon={<CloudUploadIcon />}
        type="submit"
      >
        Upload
      </Button>
    </form>
  );
};

export default ImageUpload;
 image upload with validation

3. React MUI 5 Image File Upload with Preview using react-hook-form and TypeScript.

import React, { useState } from "react";
import { useForm, Controller, SubmitHandler } from "react-hook-form";
import { Button, TextField, Box, Card, CardMedia, Container } from "@mui/material";
import CloudUploadIcon from "@mui/icons-material/CloudUpload";

// Define a type for the form data
type FormData = {
  image: FileList;
};

const ImageUpload: React.FC = () => {
  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>();
  const [imagePreview, setImagePreview] = useState<string | null>(null);

  const onSubmit: SubmitHandler<FormData> = (data) => {
    // Handle the form data
    console.log(data);
  };

  // Function to handle image preview
  const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      const file = e.target.files[0];
      setImagePreview(URL.createObjectURL(file));
    }
  };

  // Validation rule for image files
  const imageValidation = {
    required: "An image file is required",
    validate: (fileList: FileList) => {
      if (fileList.length === 0) {
        return "An image file is required";
      }
      const file = fileList[0];
      const allowedTypes = [
        "image/jpeg",
        "image/png",
        "image/gif",
        "image/svg+xml",
      ];
      if (!allowedTypes.includes(file.type)) {
        return "Invalid file type. Please select an image (jpeg, png, gif, svg).";
      }
      return true;
    },
  };

  return (

    <Container maxWidth="sm">
      <form onSubmit={handleSubmit(onSubmit)}>
        <Controller
          name="image"
          control={control}
          rules={imageValidation}
          defaultValue=""
          render={({ field }) => (
            <TextField
              {...field}
              type="file"
              onChange={(e) => {
                field.onChange(e);
                handleImageChange(e);
              }}
              InputLabelProps={{ shrink: true }}
              variant="outlined"
              fullWidth
              margin="normal"
              error={!!errors.image}
              helperText={errors.image ? errors.image.message : ""}
            />
          )}
        />
        {imagePreview && (
          <Box sx={{ my: 2, display: "flex", justifyContent: "center" }}>
            <Card sx={{ maxWidth: 345 }}>
              <CardMedia component="img" image={imagePreview} alt="Preview" />
            </Card>
          </Box>
        )}
        <Button
          variant="contained"
          color="primary"
          startIcon={<CloudUploadIcon />}
          type="submit"
          sx={{ mt: 2 }}
        >
          Upload
        </Button>
      </form>
    </Container>
  );
};

export default ImageUpload;
mui react-hook-form image upload with preview
Aaronn
Aaronn

Hey there! I'm Aaronn, a Full Stack Developer who's all about React, NEXTJS, Node.js, and Tailwind CSS. I'm on a mission to craft awesome websites that look great and work even better.