3

这个官方的 react-dropzone 示例<Dropzone />中,通过将整个应用程序包装在组件中来实现全屏放置区域。我正在创建一个多路由应用程序,并且觉得将所有内容包装在<Dropzone />组件内并不是一个非常干净的解决方案。

有没有办法在 React 中创建一个全屏/页面拖放区而不将<Dropzone />组件放在根级别?

4

1 回答 1

2

创建到Dropzone表单的路径并field使用CSS.

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

容器/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;
}
于 2018-10-13T16:07:41.690 回答