Полноэкранное перетаскивание файлов в React - PullRequest
0 голосов
/ 13 октября 2018

В этом официальном примере реагирующей дропзоны, полноэкранная зона перетаскивания достигается путем помещения всего приложения в компонент <Dropzone />.Я создаю приложение для нескольких маршрутов и чувствую, что оборачивать все внутри компонента <Dropzone /> не очень чистое решение.

Есть ли способ создать полноэкранную зону / зону перетаскивания страниц в React, не помещая <Dropzone /> компонент на корневом уровне?

1 Ответ

0 голосов
/ 13 октября 2018

Создайте маршрут к форме Dropzone и настройте высоту и размер field, используя CSS.

Рабочий пример: https://codesandbox.io/s/l77212orwz (в этом примере используется Redux Form, но вы не обязаны)

container / UploadForm.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);

компоненты / showForm.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>
);

компонентов / dropzoneField.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>
);

компонентов / renderImagePreview.js

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>
  ));

стилей.css

.dropzone-container {
  text-align: center;
  background-color: #efebeb;
  height: 100%;
  width: 100%;
}

.dropzone-area {
  margin: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.upload-container {
  height: 100vh;
  width: 100%;
  margin-bottom: 10px;
}

ul {
  list-style-type: none;
}

p {
  margin-top: 0;
}
...