Search code examples
reactjsreact-hooksreact-dropzone

Access 'name' property on React Dropzone component


I'm looking to create multiple dropzones in the same component with React Dropzone and I want to handle a file from each dropzone differently. This will be part of a form with many different dropzones that each have different parameters. To start, I am trying to pass some identifying information from a particular dropzone to the useDropzone hook so I can eventually use a different function to handle each dropzone.

How can I access the name property passed through the getRootProps function so I can handle each drop, or is there a better way to accomplish this entirely? In the code below, I was able to print the event to the console, but I can't find "testtesttest" as a value anywhere in the event object. I the props from getRootProps and getInputProps are overriding the name prop I've included, even though I also put it through the getInputProps function.

import React, {useState, useEffect} from 'react';
import {useDropzone} from 'react-dropzone'
import styled from 'styled-components';

const MasterDropzone = styled.div`
    height: 150px;
    width: 80%;
    border: 3px dashed black;
`

function UploadMedia(){

    const [masterFile, setMasterFile] = useState({
        file: null,
        preview: null
    });

    const {
        getRootProps,
        getInputProps,
    } = useDropzone({
        accept: '.jpeg,.png',
        noClick: false,
        noKeyboard: true,
        onDrop: (acceptedFiles,rejected,event) => {
            console.log(event)
            setMasterFile({
                ...masterFile,
                file: acceptedFiles[0]
            })
        }
    });

    useEffect(
        () => {
            if(!masterFile.file){
                setMasterFile({
                    ...masterFile,
                    preview: undefined
                })
                return
            }
            const objectUrl = URL.createObjectURL(masterFile.file)
            setMasterFile({
                ...masterFile,
                preview: objectUrl
            })
            return () => URL.revokeObjectURL(objectUrl)
        },
        [masterFile.file]
    );
    return (
        <div>
          <h1>Upload Media</h1>
          {
          masterFile.preview 
          ? 
          <img width='300px' height='300px' src={masterFile.preview} />
          : 
          <MasterDropzone name='testtesttest' {...getRootProps({name: 'testtesttest'})}>
          <p>Drag file here or click to upload</p>
          <input name='testtesttest'{...getInputProps({name: 'testtesttest'})} />
          </MasterDropzone>
          }
         </div>
    )
}

export default UploadMedia

Solution

  • Ended up solving this by making a Dropzone component and altering what I needed for each dropzone with props thanks to Alvaro's suggestion. Here's what I did

    UploadMedia.js

    import Dropzone from './Dropzone'
    
    function UploadMedia({ title }){
    
        const [masterFile, setMasterFile] = useState({
            content: null,
            preview: null
        });
        const [subtitleFile, setSubtitleFile] = useState({
            content: null,
            preview: null
        })
    
        const [posterImage, setPosterImage] = useState({
            content: null,
            preview: null
        })
    
        const [coverImage, setCoverImage] = useState({
            content: null,
            preview: null
        })
    
        const [featureImage, setFeatureImage] = useState({
            content: null,
            preview: null
        })
    
        const masterText = <p>Master Video File</p>
    
        const subtitleText = <p>Subtitle File</p>
    
        const posterText = <p>Poster Image</p>
    
        const coverText = <p>Cover Photo</p>
    
        const featureText = <p>Feature Photo</p>
    
        async function handleSubmit(evt) {
            evt.preventDefault()
            console.log('handle files here')
        }
    
        return (
            <Container>
                <h1>Upload media for {title.titleName}</h1>
                <Form onSubmit={handleSubmit}>
                <Dropzone file={masterFile} setFile={setMasterFile} text={masterText} height='200px' width='70%'/>
                <Dropzone file={subtitleFile} setFile={setSubtitleFile} text={subtitleText} height='100px' width='70%'/>
                <Dropzone file={posterImage} setFile={setPosterImage} text={posterText} height='200px' width='100px'/>
                <Dropzone file={coverImage} setFile={setCoverImage} text={coverText} height='150px' width='350px'/>
                <Dropzone file={featureImage} setFile={setFeatureImage} text={featureText} height='200px' width='400px'/>
                <button type="submit">Save And Upload</button>
                </Form>
            </Container>
        )
    }
    
    export default UploadMedia
    

    Dropzone.js

    function Dropzone({file, setFile, height, width, text}){
    
        const {
            getRootProps,
            getInputProps,
        } = useDropzone({
            acceptedFiles: '',
            noClick: false,
            noKeyboard: true,
            onDrop: (acceptedFiles) => {
                setFile({
                    ...file,
                    content: acceptedFiles[0]
                })
            }
        });
    
        useEffect(
            () => {
                if(!file.content){
                    setFile({
                        ...file,
                        preview: undefined
                    })
                    return
                }
                const objectUrl = URL.createObjectURL(file.content)
                setFile({
                    ...file,
                    preview: objectUrl
                })
                // this line prevents memory leaks, but also removes reference to the image URL
                // google chrome will remove this automatically when current session ends
    
                // return () => URL.revokeObjectURL(objectUrl)
            },
            [file.content]
        );
    
        return (
            <Container height={height} width={width}>
            {
            file.preview 
            ? 
            <img width='40px' height='40px' src={file.preview} />
            : 
            <DropzoneContainer {...getRootProps()}>
            {text}
            <p>Drag file or click to upload file</p>
            <input {...getInputProps()} />
            </DropzoneContainer>
            }
            </Container>
        )
    }
    
    export default Dropzone