Untitled

mail@pastecode.io avatar
unknown
javascript
2 years ago
3.1 kB
3
Indexable
Never
import { useEffect, useState } from "react";
import { useDropzone } from "react-dropzone";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import { nanoid } from "nanoid";

import { addPreviewTofileObject, filterById } from "src/utils/functions";

import "./style.css";

function Dropzone(props) {
  const [files, setFiles] = useState([]);
  const { getRootProps, getInputProps, open } = useDropzone({
    // Disable click and keydown behavior
    onDrop: (acceptedFiles) => {
      const newFiles = acceptedFiles.map((f) => ({
        id: nanoid(),
        file: addPreviewTofileObject(f),
      }));

      setFiles((prevFiles) => [...prevFiles, ...newFiles]);
    },
  });

  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);

    return result;
  };

  const onDragEnd = (result) => {
    // dropped outside the list
    if (!result.destination) {
      return;
    }

    setFiles((items) => {
      return reorder(items, result.source.index, result.destination.index);
    });
  };

  const deleteFile = (fileId) => {
    setFiles((files) => filterById(files, fileId));
  };

  useEffect(() => {
    // Make sure to revoke the data uris to avoid memory leaks, will run on unmount
    return () =>
      files.forEach((file) => URL.revokeObjectURL(file.file.preview));
  }, []);

  return (
    <div className="container">
      <div {...getRootProps({ className: "dropzone" })}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here</p>
        <button type="button" onClick={open}>
          Open File Dialog
        </button>
      </div>
      <aside>
        <h4>Files</h4>
        <DragDropContext onDragEnd={onDragEnd}>
          <Droppable droppableId="droppable" direction="horizontal">
            {(provided, snapshot) => (
              <div
                className="preview-images"
                ref={provided.innerRef}
                {...provided.droppableProps}
              >
                {files.map(({ id, file }, index) => (
                  <Draggable key={id} draggableId={id} index={index}>
                    {(provided, snapshot) => (
                      <div
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                      >
                        <img
                          key={id}
                          className="preview-image"
                          src={file.preview}
                          alt=""
                          onLoad={() => {
                            URL.revokeObjectURL(file.preview);
                          }}
                        />
                        <button onClick={() => deleteFile(id)}>delete</button>
                      </div>
                    )}
                  </Draggable>
                ))}
              </div>
            )}
          </Droppable>
        </DragDropContext>
      </aside>
    </div>
  );
}

export default Dropzone;