title: Is there any good way to connect react-image-crop with react-dropzone?
body: <p>I've been trying to connect react-image-crop with react dropzone, but it's just doesn't seem to work, or i am doing something really wrong.</p>
  <p>that's my drag and drop component</p>
  <pre><code> import { useDropzone } from 'react-dropzone';
  import React, { useMemo, useCallback, useEffect, useRef } from 'react';
  
  import styles from './index.module.scss';
  import { FormField, FormCheckbox, Button } from 'components/common';
  import toastr from 'utils/toastr';
  import ModalInfoCrop from '../../../ModalnfoCrop';
  
  const DragAndDrop = ({ value, onChange, field, form }) =&gt; {
    const uploadInputRef = useRef(null);
  
    useEffect(
      () =&gt; () =&gt; {
        files.forEach((file) =&gt; URL.revokeObjectURL(file.preview));
      },
      [files]
    );
  
    const files = useMemo(() =&gt; {
      return (field &amp;&amp; field.value) || value || [];
    }, [field, value]);
  
    const onFileAdd = useCallback(
      (files) =&gt; {
        if (field &amp;&amp; form) {
          form.setFieldValue(field.name, files);
        } else {
          onChange &amp;&amp; onChange(files);
        }
      },
      [field, form, onChange]
    );
    const error = useMemo(() =&gt; !!(field &amp;&amp; form &amp;&amp; form.errors[field.name]), [
      field,
      form,
    ]);
  
    const { getRootProps, getInputProps } = useDropzone({
      accept: 'image/*',
      onDrop: (acceptedFiles) =&gt; {
        let files_arr = files;
        if (files.length) {
          acceptedFiles.forEach((element) =&gt; {
            if (element.size &lt;= 15728640) {
              let isRepeated = false;
              files.forEach((file) =&gt; {
                if (file.name === element.name) {
                  isRepeated = true;
                  return;
                }
              });
              if (!isRepeated) {
                files_arr.push(element);
              }
            } else {
              toastr.error(`File ${element.name} is more than MB`);
            }
          });
        } else {
          files_arr = acceptedFiles;
        }
        onFileAdd(
          files_arr.map((file) =&gt;
            Object.assign(file, {
              preview: URL.createObjectURL(file),
            })
          )
        );
      },
    });
  
    const changeMainPhoto = (e) =&gt; {
      e.preventDefault();
      let mainImageIndex = +e.target.getAttribute('data-fileindex');
      form.setFieldValue('mainPhotoIndex', mainImageIndex);
    };
  
    const deletePhoto = (deletedIndex) =&gt; {
      files.splice(deletedIndex, 1);
  
      if (deletedIndex === form.values.mainPhotoIndex)
        form.setFieldValue('mainPhotoIndex', 0);
  
      onFileAdd(
        files.map((file) =&gt;
          Object.assign(file, {
            preview: URL.createObjectURL(file),
          })
        )
      );
    };
  
    const thumbs = files.map((file, index) =&gt; (
      &lt;div className={styles.thumb} key={index}&gt;
        &lt;div className={styles.thumbInner}&gt;
          &lt;img
            src={(file &amp;&amp; file.preview) || file}
            className={styles.imgInner}
            alt=&quot;item_photo&quot;
          /&gt;
          &lt;FormCheckbox
            value={form.values.mainPhotoIndex === index}
            onClick={changeMainPhoto}
            inputProps={{ 'data-fileindex': index }}
            className={styles.mainImageCheckBox}
            name=&quot;&quot;
          /&gt;
          &lt;Button
            onClick={() =&gt; deletePhoto(index)}
            color=&quot;secondary&quot;
            className={styles.imageDeleteButton}
          &gt;
            X
          &lt;/Button&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    ));
  
    return (
      &lt;&gt;
        &lt;section className={error ? styles.wrapper_error : styles.wrapper}&gt;
          &lt;div
            {...getRootProps({ className: 'dropzone' })}
            style={{
              margin: '.5rem 1rem',
            }}
          &gt;
            &lt;input
              name=&quot;photos&quot;
              ref={uploadInputRef}
              type=&quot;file&quot;
              {...getInputProps()}
            /&gt;
            &lt;p
              style={{
                margin: '.5rem auto',
                fontWeight: '600',
              }}
            &gt;
              Drag Photos here &lt;br /&gt; or
            &lt;/p&gt;
            &lt;div
              style={{
                backgroundColor: 'black',
                padding: '.5rem 1rem',
                color: 'white',
                borderRadius: '40px',
                margin: '.5rem 30%',
              }}
            &gt;
              + Add Photos
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/section&gt;
        &lt;aside className={styles.thumbsContainer}&gt;{thumbs}&lt;/aside&gt;
      &lt;/&gt;
    );
  };
  
  export default ({ name, ...props }) =&gt;
    name ? (
      &lt;FormField name={name} component={DragAndDrop} {...props} /&gt;
    ) : (
      &lt;DragAndDrop {...props} /&gt;
    );
  </code></pre>
  <p>and that's where the react-image-crop is, i tried multiple ways to open crop while uploading a photo, but haven't come up with a good solution, so removed everything and that's where i am now</p>
  <pre><code>import React, { Component, useState, useRef, useEffect, useCallback } from 'react';
  import ReactCrop, { makeAspectCrop } from 'react-image-crop';
  import { Button, Dialog, MuiThemeProvider } from '@material-ui/core';
  import styles from './index.module.scss';
  import { parseWithOptions } from 'date-fns/fp';
  
  const pixelRatio = 4;
  
  function getResizedCanvas(canvas, newWidth, newHeight) {
    const tmpCanvas = document.createElement(&quot;canvas&quot;);
    tmpCanvas.width = newWidth;
    tmpCanvas.height = newHeight;
  
    const ctx = tmpCanvas.getContext(&quot;2d&quot;);
    ctx.drawImage(
      canvas,
      0,
      0,
      canvas.width,
      canvas.height,
      0,
      0,
      newWidth,
      newHeight
    );
  
    return tmpCanvas;
  }
  
  function generateDownload(previewCanvas, crop) {
    if (!crop || !previewCanvas) {
      return;
    }
  
    const canvas = getResizedCanvas(previewCanvas, crop.width, crop.height);
  
    canvas.toBlob(
      blob =&gt; {
        const previewUrl = window.URL.createObjectURL(blob);
  
        const anchor = document.createElement(&quot;a&quot;);
        anchor.download = &quot;cropPreview.png&quot;;
        anchor.href = URL.createObjectURL(blob);
        anchor.click();
  
        window.URL.revokeObjectURL(previewUrl);
      },
      &quot;image/png&quot;,
      1
    );
  }
  
  export default function ModalInfoCrop(photo) {
    const [upImg, setUpImg] = useState(photo);
    const imgRef = useRef(photo);
    const previewCanvasRef = useRef(null);
    const [crop, setCrop] = useState({ unit: &quot;%&quot;, width: 30, aspect: 16 / 9 });
    const [completedCrop, setCompletedCrop] = useState(null);
  
    const onSelectFile = e =&gt; {
      if (e.target.files &amp;&amp; e.target.files.length &gt; 0) {
        const reader = new FileReader();
        reader.addEventListener(&quot;load&quot;, () =&gt; setUpImg(reader.result));
        reader.readAsDataURL(e.target.files[0]);
      }
    };
  
    const onLoad = useCallback(img =&gt; {
      imgRef.current = img;
    }, []);
  
    useEffect(() =&gt; {
      if (!completedCrop || !previewCanvasRef.current || !imgRef.current) {
        return;
      }
  
      const image = imgRef.current;
      const canvas = previewCanvasRef.current;
      const crop = completedCrop;
  
      const scaleX = image.naturalWidth / image.width;
      const scaleY = image.naturalHeight / image.height;
      const ctx = canvas.getContext(&quot;2d&quot;);
  
      canvas.width = crop.width * pixelRatio;
      canvas.height = crop.height * pixelRatio;
  
      ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
      ctx.imageSmoothingEnabled = false;
  
      ctx.drawImage(
        image,
        crop.x * scaleX,
        crop.y * scaleY,
        crop.width * scaleX,
        crop.height * scaleY,
        0,
        0,
        crop.width,
        crop.height
      );
    }, [completedCrop]);
  
    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;div&gt;
          &lt;input type=&quot;file&quot; accept=&quot;image/*&quot; onChange={onSelectFile} /&gt;
        &lt;/div&gt;
        &lt;ReactCrop
          src={upImg}
          onImageLoaded={onLoad}
          crop={crop}
          onChange={c =&gt; setCrop(c)}
          onComplete={c =&gt; setCompletedCrop(c)}
        /&gt;
      &lt;/div&gt;
    );
  }
  </code></pre>
  <p>i just have no idea on how to implement this the proper way, so i appreciate every bit of advice on it, thanks in advance</p>