Skip to main content

FileUpload Component

The FileUpload component in React allows for uploading files with specific constraints, such as file type and size. It's integrated with react-hook-form for form management, ensuring a seamless user experience.

Features

  • Supports multiple file types as defined by the AcceptedFileTypes enum.
  • Enforces a maximum file size limit.
  • Provides a user-friendly interface for dragging and dropping files.
  • Displays selected file name with an option to remove it.
  • Fully integrated with react-hook-form.

Props

PropTypeDescription
labelstringText displayed on the upload button.
namePath<TFormValues>Name for the form control, ensuring it's a valid key of TFormValues.
controlControl<TFormValues>Control object from react-hook-form, typed with TFormValues.
acceptedTypesAcceptedFileTypes[]Array of accepted file types.
maxFileSizenumberMaximum file size in bytes. The default is set to 1 MB.

Component

import React, { useCallback } from "react";
import { Controller, Control, Path, FieldValues } from "react-hook-form";

interface FileUploadProps<TFormValues extends FieldValues, AcceptedFileTypes> {
label: string;
name: Path<TFormValues>;
control: Control<TFormValues>;
acceptedTypes: AcceptedFileTypes[];
maxFileSize: number;
}

const FileUpload = <
TFormValues extends Record<string, any>,
AcceptedFileTypes
>({
label,
name,
control,
acceptedTypes,
maxFileSize = 1,
}: FileUploadProps<TFormValues, AcceptedFileTypes>) => {
// Function to validate file size
const isValidFileSize = (file: File) =>
file.size <= maxFileSize * 1024 * 1024;

// File validation handler
const handleFileValidation = (file: File | null) => {
if (file && acceptedTypes.includes(file.type) && isValidFileSize(file)) {
return file;
} else {
if (file && !isValidFileSize(file)) {
alert(`File size should not exceed ${maxFileSize} MB`);
} else {
alert("File type not accepted");
}
return null;
}
};

const handleDragOver = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
},
[]
);

return (
<div
className="flex flex-row items-center justify-center bg-gray-100 p-6 rounded-lg shadow-sm"
onDragOver={handleDragOver}
>
<Controller
control={control}
name={name}
render={({ field: { onChange, onBlur, value } }) => (
<>
<input
type="file"
id="file-upload"
className="hidden"
onBlur={onBlur}
onChange={(e) => {
const file = e.target.files ? e.target.files[0] : null;
onChange(handleFileValidation(file));
}}
/>
<label
htmlFor="file-upload"
className="cursor-pointer py-2 px-4 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700"
role="button"
tabIndex={0}
>
{label}
</label>

{value && (
<div className="flex flex-row gap-2 items-center">
<span className="text-sm block whitespace-nowrap text-ellipsis overflow-hidden w-40 text-gray-700">
{value.name}
</span>
<button
onClick={() => onChange(null)}
className="py-1 px-3 bg-red-500 text-white font-semibold rounded hover:bg-red-700"
>
X
</button>
</div>
)}
</>
)}
/>
</div>
);
};

export default FileUpload;

Usage

To use the FileUpload component, import it into your form component. Ensure the form is managed by react-hook-form for optimal functionality.

enum AcceptedFileTypes {
JPEG = "image/jpeg",
PNG = "image/png",
// Add more types as needed
}

type Props = {
// PropTypes
};

type LoginForm = {
upload: File;
};

const App = (props: Props) => {
return (
<div className="flex justify-center items-center flex-col">
<form onSubmit={handleSubmit(onSubmit)}>
<FileUpload<LoginForm, AcceptedFileTypes>
label="Upload File"
control={control}
maxFileSize={1}
name="upload"
acceptedTypes={[AcceptedFileTypes.JPEG, AcceptedFileTypes.PNG]}
/>
<button
type="submit"
className="mt-4 bg-blue-500 text-white p-2 rounded"
>
Submit
</button>
</form>
</div>
);
};

Styling

The component uses Tailwind CSS for styling. Customize the styles by modifying the Tailwind classes within the component.

Accessibility

Basic accessibility features are integrated, such as keyboard navigability and focus management. Additional accessibility improvements can be made based on specific use cases.

Dependencies

  • React ^17.0.0 or higher
  • react-hook-form ^7.0.0 or higher
  • Tailwind CSS for styling

Notes

  • The FileUpload component is designed for scenarios requiring file uploads with specific type and size constraints.
  • The component's functionality and appearance can be customized to fit the needs of your application.

This documentation provides a comprehensive overview

of the FileUpload component, including its features, props, usage, and dependencies. Adjust paths and versions as per your project setup.