Day 32


画像のプレビュー


FileReader
JavaScriptの機能です.プレビューはできますが、パソコンに保存されているので、他の人には見えません.後続file Reader.readAsData URL(ファイル)は、ファイルにURLを作成します.fileReader.onloadロード.
export default function ImageUploadPreviewPage() {
  function onChangeFile(event) {
    const myFile = event.target.files[0];
    console.log(myFile);

    const fileReader = new FileReader();
    fileReader.readAsDataURL(myFile);
    fileReader.onload = (data) => {
      console.log(data.target.result);
    };
  }

  return <input type="file" onChange={onChangeFile}></input>;
}

では、こんなに長い住所があります.最後までコピーして、このアドレスに入るとプレビューできます.ではこれをStateに入れて皆さんに見せましょう
import { useState } from "react";

export default function ImageUploadPreviewPage() {
  const [imageUrl, setimageUrl] = useState("");
  function onChangeFile(event) {
    const myFile = event.target.files[0];
    console.log(myFile);

    const fileReader = new FileReader();
    fileReader.readAsDataURL(myFile);
    fileReader.onload = (data) => {
      console.log(data.target.result);
      setimageUrl(data.target?.result);
    };
  }

  return (
    <>
      <img src={imageUrl} />
      <input type="file" onChange={onChangeFile}></input>
    </>
  );
}
そうなるとパソコンでurlに変えてアップロードすると非常に高速になります
しかし、登録投稿ボタンをクリックすると、そのURLをアップロードしても他の人には見えません.
最終的には、ある場所でアップロードファイルリクエストを発行する必要があります.
では、登録ボタンで投稿をファイルアップロード+アップロードしたファイルとして登録する必要があります.
アップロードされたファイルを使用して投稿を登録する場合は、setimageUrlはプレビュー用の偽アドレスにすぎないことを知っておく必要があります.+その後、本物のファイルをstateに入れる必要があります.
setmyfile(ファイル)でアップロードします.
import { useState } from "react";
import { gql, useMutation } from "@apollo/client";
import {
  IMutation,
  IMutationCreateBoardArgs,
} from "../../src/commons/types/generated/types";

const UPLOAD_FILE = gql`
  mutation uploadFile($file: Upload!) {
    uploadFile(file: $file) {
      url
    }
  }
`;

const CREATE_BOARD = gql`
  mutation createBoard($createBoardInput: CreateBoardInput!) {
    createBoard(createBoardInput: $createBoardInput) {
      _id
      images
    }
  }
`;

export default function ImageUploadPreviewPage() {
  const [imageUrl, setimageUrl] = useState("");
  const [myFile, setmyfile] = useState();
  const [createBoard] = useMutation(CREATE_BOARD);
  const [uploadFile] = useMutation(UPLOAD_FILE);

  function onChangeFile(event) {
    const file = event.target.files[0];
    console.log(file);

    const fileReader = new FileReader();
    fileReader.readAsDataURL(file);
    fileReader.onload = (data) => {
      console.log(data.target.result);
      setimageUrl(data.target?.result);
      setmyfile(file);
    };
  }

  async function onClickSumbmit() {
    let myImageUrl = "";

    // 1. 파일업로드
    if (myFile) {
      const result1 = await uploadFile({
        variables: {
          file: myFile,
        },
      });
      myImageUrl = result1.data?.uploadFile.url || "";
    }

    // 2. 업로드된 파일로 게시물 등록
    const result2 = await createBoard({
      variables: {
        createBoardInput: {
          writer: "영희",
          password: "1234",
          title: "안녕하세요~~",
          contents: "이미지 업로드 연습중임",
          images: [myImageUrl],
        },
      },
    });
    console.log(result2.data?.createBoard._id);
  }

  return (
    <>
      <img src={imageUrl} />
      <input type="file" onChange={onChangeFile}></input>
      <button onClick={onClickSumbmit}> 등록하기</button>
    </>
  );
}

このように登録を押すと、アカウントの値を出すことができます.
しかし、1つのファイルで登録すればいいです.
しかし、複数あると5つのプレビューが容易に+になりますが登録するときは、5つのファイルを1つずつアップロードファイルに転送します.では、5つのファイルのアップロードを待つ必要があり、待つ部分が増えます.
だから改善すれば?

Promise all


まず、Promise allのないマルチイメージアップロードを作成します.
  const [myFiles, setmyfiles] = useState([]);
myFileをFilesに置き換え、複数([])配列に設定
      setmyfiles((prev) => [...prev, file]);
setmyFilesで以前のファイル+で追加したファイルを塗りつぶします.

3つ作るならそうするかもしれない0、1、2個のmyImageUrlsごとに空の配列が入ります.
if (myFiles.length) {
   const start = performance.now();
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   await uploadFile({ variables: { file: myFiles[0] } });
   const end = performance.now();
   console.log(end - start);
   }
   }
みんな待ってるなら
 const start = performance.now();
      await Promise.all([
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
        uploadFile({ variables: { file: myFiles[0] } }),
      ]);
      const end = performance.now();
      console.log(end - start);
Promise allは一度にアップロードできます.ちょっと待ってください.
スピード、これはもっと速い


5000/50こつこつ

アップロードのパフォーマンス


レンダーのパフォーマンス(Render Performance)


pre-load
事前にロードして表示すると、速度が速くなります.
useEffectを使用してstateを読み込むとすぐに
import { useEffect, useState } from "react";

export default function ImagePreloadPage() {
  const [myLoadedImage, setMyLoadedImage] = useState();
  const divRef = useRef(null);

  useEffect(() => {
    const img = new Image();
    img.src = "https://codebootcamp.co.kr/images/main/homeImage1.webp";
    img.onload = () => {
      setMyLoadedImage(img);
    };
  });
  function onClickButton() {
    divRef.current?.appendChild(myLoadedImage);
  }
  return (
    <>
      <h1>안녕하세요 사이트에 오신 것을 환연합니다!!</h1>
      <div ref={divRef}></div>
      <button onClick={onClickButton}>이미지 보여주기</button>
      {/* <img src="https://codebootcamp.co.kr/images/main/homeImage1.webp" /> */}
    </>
  );
}
最初は画像が見えませんでしたが.
画像ラベルを使用して画像(ダウンロード済み)をインポートonloadで画像をインポートする場合->stateに画像を入れる様子.
次にボタンをクリックし、ボタン内でdivに画像を貼り付けます.
イメージロードが完了しているので、実行すると単独でダウンロードするのではなく、直接展示します.
LazyLoading
https://www.npmjs.com/package/react-lazyload
すべてを最初からダウンロードするには、速度が遅くなります.
レーザーロッドを使用してスクロールする場合は、それをロードすることが望ましい.

使い方はLazyLoadで包んでください
ページ速度チェック
https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect&hl=ko

(スマホでもチェックできます)
このように性能改善方法を提案する

画像のパフォーマンスへの影響は小さい
拡張子も同様
++加算
https://www.npmjs.com/package/react-dropzone
ドラッグ&ドロップ画像アップロードライブラリ
https://www.npmjs.com/package/react-avatar-editor

写真調整機能付きライブラリ
https://www.npmjs.com/package/react-beautiful-dnd
構成部品のドラッグと配置を許可
サマリ
画像をアップロードすることは性能向上にとって非常に重要であり、複数の画像をアップロードする際に規則を使用する
画像をアップロードするだけでなく、承諾さえすれば、テキストはどうでもいい.
race-先に終わったことに気づいた
約束は大切
パフォーマンスの向上には、拡張子(webp)、userEffectとしてプリフェッチ、appendChild+として表示される有用なライブラリを使用します.