反応でカスタムドラッグ&ドロップフックを作成する方法!🔥

34578 ワード

こんにちは!
最近、プロジェクトに取り組んでいる間、サーバーにファイルをアップロードするためのドラッグアンドドロップ機能を実装する必要がありました.しかし、問題は、私が働いていた(コンポーネント)ファイルが既に大きかったので、私はどうにか、私の構成要素ロジックからドラッグアンドドロップロジックを切り離したいと思いました、そして、私は結局useDragAndDrop()フックを作成しました.
この記事では、私は正確に、どのようにドラッグアンドドロップ機能のカスタムフックを作成して共有したい.
だから、それを構築しましょう!🔥
私たちに、私たちが何を築くかの最終結果を示しましょう.

反応プロジェクトを初期化します。

npx create-react-app drag-and-drop-react --template typescriptプロジェクトが初期化された後、アプリケーションでフォームを作成しましょう.js
import "./App.css";

function App() {
  return (
    <div className="container">
      <form>
        <label htmlFor="file">
          <h1>Select Or drop a file</h1>
        </label>
        <input type="file" name="file" id="file" />
      </form>
    </div>
  );
}

export default App;
アプリで.CSSは、それは美しく見えるように、次の変更を行うか、独自のカスタムスタイリングを行うことができます!

@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html,
body {
  background: #0267c1;
  height: 100vh;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  background: #fff;
  padding: 3em 5em;
  border-radius: 0.5em;
  box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.02),
    0 6.7px 5.3px rgba(0, 0, 0, 0.028), 0 12.5px 10px rgba(0, 0, 0, 0.035),
    0 22.3px 17.9px rgba(0, 0, 0, 0.042), 0 41.8px 33.4px rgba(0, 0, 0, 0.05),
    0 100px 80px rgba(0, 0, 0, 0.07);
}

input {
  display: none;
}

label {
  width: 400px;
  border: 3px #efa00b dashed;
  padding: 3em 1.78em;
  display: inline-block;
  cursor: pointer;
  font-family: "Noto Sans JP", sans-serif;
}

label h1 {
  font-size: 130%;
  text-align: center;
  color: #efa00b;
}

.file-drop-error {
  width: 100%;
  text-align: center;
  color: red;
  display: inline-block;
  margin-bottom: 1em;
}

.file-properties {
  margin-top: 1em;
}

.file-properties ul {
  list-style: none;
  text-align: center;
}

さあ、フックを作ろう


フックと呼ばれるフォルダを作成し、その中で“usedraganddrop . ts”ファイルを作成します.このファイルでは、ドラッグアンドドロップ機能の必要な状態とメソッドを作成します.
まず、2つの状態ドラグオーバーとfiledroperrorを作成します.DragOverはファイルが我々のLabel要素の上でドラッグされているかどうか決定します、そして、filedroperrorはエラーメッセージがファイルを落とした後にあるならば、エラーメッセージを含みます.この場合、我々はイメージが欲しいので、filedroperrorはファイルに関連しているエラーメッセージをタイプイメージでないことをたぶん格納します.
  const [dragOver, setDragOver] = useState(false);
  const [fileDropError, setFileDropError] = useState(")

次に、DragOver ()とOnDragLeave ()の2つの関数を作成します.これは、ドラッグオーバーの状態をトグルし、すべての状態とメソッドを返します.
 const onDragOver = (e: React.SyntheticEvent) => {
    e.preventDefault();
    setDragOver(true);
  };

  const onDragLeave = () => setDragOver(false);
最終的なコードはこのようになります.
import { useState } from "react";

export default function useDragAndDrop() {
  const [dragOver, setDragOver] = useState(false);
  const [fileDropError, setFileDropError] = useState("")

  const onDragOver = (e: React.SyntheticEvent) => {
    e.preventDefault();
    setDragOver(true);
  };

  const onDragLeave = () => setDragOver(false);

  return {
    dragOver,
    setDragOver,
    onDragOver,
    onDragLeave,
    fileDropError,
    setFileDropError,
  };
}
そして、それはこのファイルのためです.さて、アプリに戻ってみましょう.JSと私たちのフックを実装します.
フックフォルダから「インポート」「使用」を選択します.それから、フックからすべての値を切り離してください.ファイルを保存するファイル状態も必要です.
import React, { useState } from "react";
import "./App.css";
import useDragAndDrop from "./hooks/useDragAndDrop";

function App() {
  const [file, setFile] = useState<File>();

  const {
    dragOver,
    setDragOver,
    onDragOver,
    onDragLeave,
    fileDropError,
    setFileDropError,
  } = useDragAndDrop();

 return (
    <div className="container">
      <form>
        <label htmlFor="file">
          <h1>Select Or drop a file</h1>
        </label>
        <input type="file" name="file" id="file" />
      </form>
    </div>
}
さて、このようなラベルにonDragOverとOnDragLeaveメソッドを指定しましょう.ondrop関数がフックに関連していないことに注意してください.我々は、アプリケーションでこの関数を作成します.js自体.
また、条件付きスタイリングと条件付きレンダリングを追加します.ファイルがラベルの上にドラッグされるならば、これはちょうど境界スタイルとラベルの中のテキストを変えます.下の写真を見てください
         <label
          htmlFor="file"
          onDragOver={onDragOver}
          onDragLeave={onDragLeave}
          onDrop={onDrop}
          style={{ border: `${dragOver ? "3px dashed yellowgreen" : ""}` }}
        >
          {file && <h1>{file.name}</h1>}
          {!file && (
            <h1 style={{ color: `${dragOver ? " yellowgreen" : ""}` }}>
              {!dragOver ? "Select Or Drop your File here..." : "Drop here..."}
            </h1>
          )}
        </label>

さあ、ファイルをドロップしたり選択した後にファイル状態を設定するondrop ()とfileselect ()関数を作成します.
   const onDrop = (e: React.DragEvent<HTMLLabelElement>) => {
    e.preventDefault();

    setDragOver(false);

    const selectedFile = e?.dataTransfer?.files[0];

    if (selectedFile.type.split("/")[0] !== "image") {
      return setFileDropError("Please provide an image file to upload!");
    }

    setFile(selectedFile);
  };

  const fileSelect = (e: any) => {
    let selectedFile = e?.dataTransfer?.files[0];

    if (selectedFile.type.split("/")[0] !== "image") {
      return setFileDropError("Please provide an image file to upload!");
    }

    setFileDropError("");
  };
入力要素にOnChangeハンドラを記述します.<input type="file" name="file" id="file" onChange={fileSelect} />また、条件付きでエラーが発生する必要があります.
 {fileDropError && (
    <span className="file-drop-error">{fileDropError}</span>
 )}
ファイナルアプリ.JSはこのように見えます.
import React, { useState } from "react";
import "./App.css";
import useDragAndDrop from "./hooks/useDragAndDrop";

function App() {
  const {
    dragOver,
    setDragOver,
    onDragOver,
    onDragLeave,
    fileDropError,
    setFileDropError,
  } = useDragAndDrop();

  const [file, setFile] = useState<File>();

  const onDrop = (e: React.DragEvent<HTMLLabelElement>) => {
    e.preventDefault();

    setDragOver(false);

    const selectedFile = e?.dataTransfer?.files[0];

    if (selectedFile.type.split("/")[0] !== "image") {
      return setFileDropError("Please provide an image file to upload!");
    }

    setFile(selectedFile);
  };

  const fileSelect = (e: any) => {
    let selectedFile = e?.dataTransfer?.files[0];

    if (selectedFile.type.split("/")[0] !== "image") {
      return setFileDropError("Please provide an image file to upload!");
    }

    setFileDropError("");
  };

  return (
    <div className="container">
      <form>
        {fileDropError && (
          <span className="file-drop-error">{fileDropError}</span>
        )}
        <label
          htmlFor="file"
          onDragOver={onDragOver}
          onDragLeave={onDragLeave}
          onDrop={onDrop}
          style={{ border: `${dragOver ? "3px dashed yellowgreen" : ""}` }}
        >
          {file && <h1>{file.name}</h1>}
          {!file && (
            <h1 style={{ color: `${dragOver ? " yellowgreen" : ""}` }}>
              {!dragOver ? "Select Or Drop your File here..." : "Drop here..."}
            </h1>
          )}
        </label>
        <input type="file" name="file" id="file" onChange={fileSelect} />
      </form>
    </div>
  );
}

export default App;

そして、それは我々が正常にカスタムドラッグ&ドロップフックを作成している!


あなたが記事が好きで、同様に若干の知識を得たことを願っています.使用されるすべてのコードは、以下に記載されているgithubリポジトリにあります.
ギタブレポ