created: 2020-10-31T07:54:36.000Z

React/Formikでファイルのドラッグアンドドロップ

Formikに渡すコンポーネントはこんな感じのをつくる

const { setStatus, status } = props;
const { isFileDragging } = status;
return (
    <label
        className={classNames("dropzone", { isFileDragging })}
        onDragOver={() =>
            setStatus({ ...status, isFileDragging: true })
        }
        onDragLeave={() =>
            setStatus({ ...status, isFileDragging: false })
        }
    >
        <input
        name="file"
        type="file"
        onChange={async (event: any) => {
            if (event.currentTarget.files) {
                await props.setFieldValue(
                    "file",
                    event.currentTarget.files[0]
                );
                await props.submitForm();
            }
        }}
        />
    </label>
)

css

ドラッグアンドドロップできる領域を作るcssについては以下の記事が参考になった

.dropzone {
  width: 600px;
  height: 180px;
  line-height: 180px;
  border-style: dotted;
  border-width: 2px;
  border-color: #ccc;
  color: #ccc;
  text-align: center;

  position: relative;
  input[type=file] {
    opacity: 0;
    height: 100%;
    width: 100%;
    display: block;
  }
}

こんなロジックでCSSを定義するようだ

  • labelの中にinput要素を入れる
  • label要素を
    • position: relative;
      • 子要素で100%を指定しても親要素を超えなくなる
  • input要素を
    • labelの領域 = input[type=file]の領域 となるようする
      • height: 100%;
      • width: 100%;

classNames

動的にclassNameを変更するときは classNames パッケージが使いやすい