在React中全屏拖放文件

时间:2018-10-13 10:44:01

标签: reactjs drag-and-drop react-dropzone

在react-dropzone的this official example中,通过将整个应用包装在<Dropzone />组件内,可以实现全屏拖放区域。我正在创建一个多路线应用程序,觉得将所有内容包装在<Dropzone />组件中并不是一个很干净的解决方案。

有没有一种方法可以在React中创建一个全屏/页面放置区域,而无需将<Dropzone />组件放在根级别?

1 个答案:

答案 0 :(得分:0)

使用eval创建到Dropzone格式的路线,并调整field的高度和大小。

工作示例:https://codesandbox.io/s/l77212orwz(此示例使用Redux Form,但您不必这样做)

container / UploadForm.js

CSS

components / showForm.js

import React, { Component } from "react";
import { reduxForm } from "redux-form";
import ShowForm from "../components/showForm";

class UploadImageForm extends Component {
  state = { imageFile: [] };

  handleFormSubmit = formProps => {
    const fd = new FormData();
    fd.append("imageFile", formProps.imageToUpload[0]);
    // append any additional Redux form fields
    // create an AJAX request here with the created formData
  };

  handleOnDrop = newImageFile => this.setState({ imageFile: newImageFile });

  resetForm = () => {
    this.setState({ imageFile: [] });
    this.props.reset();
  };

  render = () => (
    <div style={{ padding: 10 }}>
      <ShowForm
        handleOnDrop={this.handleOnDrop}
        resetForm={this.resetForm}
        handleFormSubmit={this.handleFormSubmit}
        {...this.props}
        {...this.state}
      />
    </div>
  );
}

export default reduxForm({ form: "UploadImageForm" })(UploadImageForm);

components / dropzoneField.js

import isEmpty from "lodash/isEmpty";
import React from "react";
import { Form, Field } from "redux-form";
import DropZoneField from "./dropzoneField";

const imageIsRequired = value => (isEmpty(value) ? "Required" : undefined);

export default ({
  handleFormSubmit,
  handleOnDrop,
  handleSubmit,
  imageFile,
  pristine,
  resetForm,
  submitting
}) => (
  <Form onSubmit={handleSubmit(handleFormSubmit)}>
    <Field
      name="imageToUpload"
      component={DropZoneField}
      type="file"
      imagefile={imageFile}
      handleOnDrop={handleOnDrop}
      validate={[imageIsRequired]}
    />
    <button
      type="submit"
      className="uk-button uk-button-primary uk-button-large"
      disabled={submitting}
    >
      Submit
    </button>
    <button
      type="button"
      className="uk-button uk-button-default uk-button-large"
      disabled={pristine || submitting}
      onClick={resetForm}
      style={{ float: "right" }}
    >
      Clear
    </button>
  </Form>
);

components / renderImagePreview.js

import React, { Fragment } from "react";
import DropZone from "react-dropzone";
import { MdCloudUpload } from "react-icons/md";
import RenderImagePreview from "./renderImagePreview";

export default ({
  handleOnDrop,
  input,
  imagefile,
  meta: { error, touched }
}) => (
  <div>
    <DropZone
      accept="image/jpeg, image/png, image/gif, image/bmp"
      className="upload-container"
      onDrop={handleOnDrop}
      onChange={file => input.onChange(file)}
    >
      <div className="dropzone-container">
        <div className="dropzone-area">
          {imagefile && imagefile.length > 0 ? (
            <RenderImagePreview imagefile={imagefile} />
          ) : (
            <Fragment>
              <MdCloudUpload style={{ fontSize: 100, marginBottom: 0 }} />
              <p>Click or drag image file to this area to upload.</p>
            </Fragment>
          )}
        </div>
      </div>
    </DropZone>
    {touched && error && <div style={{ color: "red" }}>{error}</div>}
  </div>
);

styles.css

import map from "lodash/map";
import React from "react";

export default ({ imagefile }) =>
  map(imagefile, ({ name, preview, size }) => (
    <ul key={name}>
      <li>
        <img src={preview} alt={name} />
      </li>
      <li style={{ textAlign: "center" }} key="imageDetails">
        {name} - {size} bytes
      </li>
    </ul>
  ));