Back to all questions

How to use Dropzone with @mantine/form?

Last updated

@mantine/dropzone package provides Dropzone component which allows to drag and drop files from your computer or select them using the file picker. Its purpose is to handle file selection, it does not store files state, does not display selected files and does not upload them to the server.

use-form hook handles form state, validation, error messages and form submission. You can integrate any input or React component with use-form hook using the following form object properties:

  • form.values.x – value of the input
  • form.errors.x – error message for the input
  • form.setFieldValue('x', value) – function to set input value
  • form.setFieldError('x', 'error-message') – function to set input error message

Using these properties you can integrate Dropzone with use-form hook:

import { useForm } from '@mantine/form';
import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
import { Center, Text, CloseButton } from '@mantine/core';

interface FormValues {
  files: File[];
}

function Demo() {
  const form = useForm<FormValues>({
    initialValues: { files: [] },
  });

  const selectedFiles = form.values.files.map((file, index) => (
    <Text key={file.name}>
      <b>{file.name}</b> ({(file.size / 1024).toFixed(2)} kb)
      <CloseButton
        size="xs"
        onClick={() =>
          form.setFieldValue(
            'files',
            form.values.files.filter((_, i) => i !== index)
          )
        }
      />
    </Text>
  ));

  return (
    <>
      <Dropzone
        h={120}
        p={0}
        multiple
        accept={[MIME_TYPES.png, MIME_TYPES.jpeg, MIME_TYPES.svg]}
        onDrop={(files) => form.setFieldValue('files', files)}
        onReject={() => form.setFieldError('files', 'Select images only')}
      >
        <Center h={120}>
          <Dropzone.Idle>Drop files here</Dropzone.Idle>
          <Dropzone.Accept>Drop files here</Dropzone.Accept>
          <Dropzone.Reject>Files are invalid</Dropzone.Reject>
        </Center>
      </Dropzone>

      {form.errors.files && (
        <Text c="red" mt={5}>
          {form.errors.files}
        </Text>
      )}

      {selectedFiles.length > 0 && (
        <>
          <Text mb={5} mt="md">
            Selected files:
          </Text>
          {selectedFiles}
        </>
      )}
    </>
  );
}