Day 32
13006 ワード
画像のプレビュー
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+として表示される有用なライブラリを使用します.
Reference
この問題について(Day 32), 我々は、より多くの情報をここで見つけました https://velog.io/@john_with_smile/Day-32テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol