오늘 한 일 :
1.aws에 image 업로드하기
2.image 업로드하는 컴포넌트 작성
3.MDN으로 기초다지기
리액트 렌더링 횟수 추적하기
질문이 있다.
import React, { useState } from 'react';
import { Modal } from 'src/components/atoms';
import { ImageUpload } from 'src/components/atoms';
export const CreateArticleModal = () => {
const [imageUrl, setImageUrl] = useState<string>();
return (
<Modal>
<ImageUpload setImageUrl={setImageUrl} />
</Modal>
);
};
/* eslint-disable @next/next/no-img-element */
import React from 'react';
import { useS3Upload } from 'next-s3-upload';
import { compressImage } from 'src/utils';
import { usePreview } from 'src/hooks';
interface Props {
setImageUrl: (e: string) => void;
}
export const ImageUpload = ({ setImageUrl }: Props) => {
const [preview, setPreview] = usePreview();
const { FileInput, openFileDialog, uploadToS3 } = useS3Upload();
const handleFileChange = async (file: File) => {
setPreview(file);
const compressedImage = await compressImage(file);
const { url } = await uploadToS3(compressedImage);
setImageUrl(url);
};
return (
<div>
<FileInput onChange={handleFileChange} />
<button onClick={openFileDialog}>Upload file</button>
{preview && <img src={preview} alt="preview image" />}
</div>
);
};
import React, { useState, useEffect, useMemo } from 'react';
export const usePreview = () => {
const [file, setFile] = useState<File>();
const [preview, setPreview] = useState<any>(); // NOTE : any 수정
const reader = useMemo(() => {
return new FileReader();
}, []);
useEffect(() => {
if (file) {
reader.readAsDataURL(file);
reader.onloadend = () => {
setPreview(reader.result);
};
}
}, [reader, file]);
return [preview, setFile] as const;
};
이런 구조로 되어있는 컴포넌트가 있다.
이때 ImageUpload라는 컴포넌트에서 특정 파일을 선택하면 ImageUpload는 몇번 렌더링될까?
우선 ImageUpload 에서 몇번 렌더링이 되는지 확인해보려고 콘솔을 찍어보았다. 그랬더니 4번 렌더링되고 있었다.
왜 4번 렌더링이 되는 것일까? 이유가 궁금하다. 내 입장에서 저 친구는 4번 렌더링이 될 필요가 없다.
Profiler에서 해당 컴포넌트가 왜 렌더링 되었는지 찾아준다. 그래서 확인해봤다.
아니 나는 렌더링이 되는 모든 원인을 찾아주는 줄 알았다. 그런데 왠걸, 하나밖에 알려주지 않는다. Hook 1 changed.
그리고 그 밑에는 언제언제 렌더링이 되었는지 알려준다. 5.8, 5.8, 6, 6.1 이렇게 총 4번. 그런데 마지막에는 1.6ms가 걸린다.
1.6ms가 걸리는걸 보니 아마도 이미지를 화면에 그리는 중인 것 같다.
우선 저 Hook 1 changed는 뭘 말하는것일까? (처음에는 이것이 말하는 것이 훅이 1번 변경되었다고 말하는 것인줄 알았는데, 그게 아니라 1번 훅이 변경되었다는 말을 하는 것 같았다. 이렇게 생각한 이유는 아래에서 setPreview를 제거하고 확인했더니 Hook 6 changed라고 나왔기 때문이다.)
우선 렌더링을 일으키는 원인을 하나씩 차근차근 살펴보려고 한다.
무엇이 렌더링을 일으키는지 찾아나가기 위해 내가 선택한 방법은 렌더링을 일으킬 것 같은 친구들을 하나씩 제거해보면서,
렌더링이 줄어드는지 확인하는 것이었다.
1.그렇게 발견한 친구 setPreview :
이 친구를 잠깐 제거하면 렌더링이 2번 줄어든다.
그럼 남아있는 2번은 무엇때문일까?
2.upLoadToS3 함수 :
의심되는 녀석은 uploadToS3함수이다. 아니나 다를까 이친구를 제거하니, 더이상 어떤 렌더링도 일어나지 않았다. 고로 이 친구로부터 렌더링이 2번 일어나고 있었던 것이다. 이 친구는 next-s3-upload라는 라이브러리에서 제공해주는 함수다. 그래서 내부를 살펴봤더니, 그곳에서 setState를 2번 사용하고 있었다. 아무래도 그래서 렌더링이 2번 일어난게 아닌가 싶다.
이 함수에 대해선 렌더링을 줄이기가 쉽지 않을 것 같다. 그냥 이 라이브러리를 이용하지 말고 내가 직접 만들어서 사용하는 것도 방법일 것 같은데, 조금 더 고민이 필요하다.
그러면 내가 컨트롤할 수 있는 부분은 setPreview이다. 이친구는 왜 2번이나 렌더링을 일으킨 것일까.
사실 이 안에서 나는 2번 setState를 사용하고 있었다. 이것을 한번으로 줄일 수는 없을까?
내가 알기로 useState는 batch update를 지원한다. 그런데 어떤 상황에서 batch update를 지원하는 것일까?
https://jwookj.tistory.com/102
이 글에 의하면 batch update는 동일한 event handler 안에 있을 때 동작하는 것 같다. 단순히 이 블로그여서라기 보다는, dan abramov가 한 말이기 때문에 신뢰가 가는 것 같다.
batch와 관련된 내용은 조금 더 찾아봐야할 것 같다. 오늘 하루가 마무리 되어가고 있다.
MDN으로 기초다지기 : 새롭게 알게된 것들
- css를 만든 그룹 : https://www.w3.org/Style/CSS/
- a태그에서 밑줄을 제거하면 접근성 점수에서 떨어질 수도 있다.
- css 적용의 우선순위 :
CSS 언어에는 충돌시 어떤 규칙이 이기는지 제어하는 규칙이 있습니다 — 이러한 규칙을 계단식(cascade) 및 우선 순위(specificity) 라고 합니다. 아래 코드 블록에서 p 선택자에 대해 두 가지 규칙을 정의했지만, 단락이 파란색으로 표시됩니다. 파란색으로 설정한 선언은 스타일 시트에서 나중에 나타나고 이후 스타일은 이전 스타일을 재정의 하기 때문입니다. 이것은 실제의 계단식 (cascade) 입니다.
그러나 기본적으로 더 구체적인 것이 이긴다. 그냥 p 태그보다는 class 선택자가 더 구체적이다. 때문에 동일한 p 태그를 가리키는 class 선택자가 위에 있고, p 태그 선택자가 아래에 있는 경우 class 선택자가 이길 것이다.
- css에도 함수가 존재한다
'TIL(Today i learned)' 카테고리의 다른 글
[TIL-2022.09.28]jest.SpyOn, createPortal 테스트코드 작성 (0) | 2022.09.28 |
---|---|
[TIL - 2022.09.27]nextjs external image 사용하기 (0) | 2022.09.27 |
[TIL-에러노트] The policy failed legacy parsing (0) | 2022.09.26 |
[TIL- 2022.09.24] 웹폰트 최적화 (0) | 2022.09.24 |
[2022.03.11 - TIL] 브런치 생성과 생산성 향상의 연관성 | 항해99 5기 (0) | 2022.03.11 |