ランサーズ(Lancers)エンジニアブログ > フロントエンド > フロントエンド定例 > Drag&Drop実装 render hooks実装 Font Awesome Icon名ずれ フロントエンド定例 2022/7/8

Drag&Drop実装 render hooks実装 Font Awesome Icon名ずれ フロントエンド定例 2022/7/8

igarashisho|2022年07月08日
フロントエンド

こんにちは、フロントエンドチームの @syo_igarashi です。
今週のフロントエンド定例の内容を記載します。

フロントエンド定例について、以前の記事(ランサーズのフロントエンドチームが取り組んでいること)でお伝えしたのですが、毎週金曜日に開催しており、実際の業務で取り組んでいることや気になった技術情報等をシェアしあう会になっています。

以下、今週の内容です。

Drag&Drop実装

当初 react-dropzone による画像のDrag&Drop実装しようかと思いましたが、
結構ライブラリ側でdocumentに対してのイベント書き込みがあったのでライブラリ使用しない形で実装しています。

https://github.com/react-dropzone/react-dropzone/blob/a2039fd/src/index.js#L521-L531


export const Component = () => {
  const onDrop = useCallback((e: React.DragEvent<HTMLDivElement>) => {
    if (e.dataTransfer.files && e.dataTransfer.files.length) {
      const files = Array.from(e.dataTransfer.files);

      uploadFile(files);
    }
  }, []);

  const onDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
    e.dataTransfer.dropEffect = 'copy';
  }, []);

  const onDragLeave = useCallback((e: React.DragEvent<HTMLDivElement>) => {
    //
  }, []);

  /**
   * react-dropzoneを使うにしても
   * 全体のdragの処理に対しての無効化を行う実装なので悩みどこだったりする
   */
  document.addEventListener(
    'dragover',
    (e) => {
      e.stopPropagation();
      e.preventDefault();
    },
    false
  );
  document.addEventListener(
    'dragleave',
    (e) => {
      e.stopPropagation();
      e.preventDefault();
    },
    false
  );
  document.addEventListener(
    'drop',
    (e) => {
      e.stopPropagation();
      e.preventDefault();
    },
    false
  );

  return (
    <div
       onDrop={onDrop}
       onDragOver={onDragOver}
       onDragLeave={onDragLeave}
    >
      <button>テキスト</button>
    </div>
  );
 }

ライブラリを使用しない形ですと上記で実装可能ですが windowやdocumentに対して関数を生やす系の実装のあるべきとはを考えるのは難しいと思いました。

render hooks実装

https://engineering.linecorp.com/ja/blog/line-securities-frontend-3/

@uhyo_さんが紹介していたhook関数の戻りにComponentを返すような実装をファイルアップロードの機能で実装してみました。

const useFileUpload = () => {
  const [files, setFiles] = useState([]);

  const FileUploadButton = () => {
    return (
      <div>
        ...(省略) setFilesに<input type="file"> に入力されたファイルを設置させる
      </div>
    );
  }

  const FileUploadList = () => {
    return files.map((file, i) => {
      return (
        <div key={i}>
          ...(省略) fileの情報を取り扱った情報を表示
        </div>
      )
    });
  }

  return {
    files,
    FileUploadButton,
    FileUploadList
  }
}

実装してみて感じたこととして、
1つの状態から生成したいコンポーネントを宣言的に書けてさらに使いまわしの効く書き方でいいなぁと思いました。

現在はカスタムフックによる処理実装がメインですが、昔あった実装設計として高階 (Higher-Order) コンポーネントとかもありましたが実装パターン名としてわかりやすいものがあるとこういった実装方法もあるという共通認識持てそうですよね。

Font Awesome Icon名ずれ

https://fontawesome.com/icons/xmark?s=solid
https://react-icons.github.io/react-icons/search?q=times

クラス名としてはfa-xmarkだけどSVG Icon名としてはFaTimesとか名称の指定が異なるものがあったりします。
Font Awesomeの公式の検索でもエイリアスとしてアイコンの検索ができますがnpmのSVG IconライブラリからimportするときとかはSVG Iconライブラリ側の検索から探した方が目的のアイコンを探せるかもしれません。
もしくはFont Awesomeの公式にあるエイリアス名をとりあえずSVG Iconライブラリ側で検索してみるというのが良いかもしれません。

 

次回の更新予定は、7/15(金)になります!

前回の定例内容はこちらから確認可能ですのでご興味いただければ下記のリンクから閲覧いただければと思います。

https://engineer.blog.lancers.jp/?s=フロントエンド定例