개발자도구 (React Developer Tools)
코드를 짜다보면, 의도와 다르게 동작하는 경우 ex) props가 제대로 출력이 안된다. 이미지가 제대로 안뜬다.
왜 안되는지 볼려면 일단 기본적으로 개발자도구를 열어서 확인한다.
크롬 웹스토어 : React Developer Tools
Component 탭을 보면
그러면 컴포넌트 insepct 가능하고 props도 다 볼수 있다.
해당 컴포넌트의 소스파일로도 갈 수 있다.
Profiler 라는 애도 슬 수 있는데
컴포넌트마다, 몇초 걸렸는지도 알 수 있음.
느린 컴포넌트에 대해서 범인 찾는 탭이다.
녹화 버튼 누르면 액션들을 보여준다.
어떤 컴포넌트들이 렌더링 되고 있는지를 알려준다.
- 서버가 느린건 예외
- Redux Dev tools 도 있음 (상태관리 tracking 가능함)
js 자르기
Single Page Application 발행하면 하나의 html, js 파일로 된다.
하나의 js 안에 모든 코드들이 들어가 있음. 사이즈가 클 수 밖에 없음. 로딩 속도가 느릴 수 밖에 없음.
이 js 파일을 잘게 분할하고 싶다면?
import {lazy, Suspense} from 'react';
const Detail = lazy(()=> import('./routes/Detail.js'));
<Suspense fallback = {<div> 로딩중임 </div>}>
<Detail></Detail>
</Suspense>
위와 같이 사용하면 lazy 하게 가져옴.
먼저 가져와야 하는것만 가져올 수 있으니 첫 화면은 빠르게 가져올 때 사용한다.
재렌더링 막는 memo, useMemo
memo
자식컴포넌트 재렌더링 막기
function Child() {
return <div> 자식임 </div>
}
...
function Cart() {
...
<Child></Child>
...
}
위와 같이 사용하면 Cart가 렌더링 될 때 Child도 재렌더링 된다. 만약 Child가 무거운 컴포넌트라면 성능에 문제를 줄 수 있다.
꼭 필요할 때만 재렌더링하려면 memo를 사용한다.
let Child = memo (function() {
return <div> 자식임 </div>
})
...
function Cart() {
...
<Child></Child>
...
}
위와 같이 memo 로 감싸주면
꼭 필요할 때만 제랜더링해줌.
memo 는 특정상황일 때만 렌더링되게 해주는 애임 특정상황?
Child가 변화될 때. 전달되는 props 값이 변화될 때
맨날 갔다 쓰면 안됨. 결국 props간에 비교작업을 계속할 것이기 때문임.
꼭 필요한 무거운 컴포넌트에만 넣어보자.
useMemo
function 함수() {
return 반복문 10억번
}
...
function Cart() {
let result = 함수();
}
이렇게라고 하면 렌더링 될 때마다 함수를 실행하니 비효율적임
이를…
function 함수() {
return 반복문 10억번
}
...
function Cart() {
let result = useMemo(() => {return 함수()}, [state]);
}
state가 변화될 때만 실행해줌.
useEffect랑 거의 동일함.
차이점은 useEffect : 렌더링 다 되고 실행 useMemo : 렌더링 될 때 실행
useTransition, useDeferreedValue
리액트 신규 기능
1. batch 기능
2. useTransition으로 느린컴포넌트 성능 향상 가능
카드 빚 돌려막기
state 1번 변경 state 2번 변경 state 3번 변경
마지막에만 딱 렌더링 일어남 (3번에서만)
리액트 18 ajax, setTimeout
<input onChange={(e) => {setName(e.target.value) }} />;
<div>{name}</div> * 10000 개
위와 같이한다면, div 1000개로 인해서 성능저하가 일어남. 굉장히 느리게 동작하는 것을 볼 수 있다.
해결책 솔루션 1. html 10000 개 지우기 솔루션 2. usetransition
import {useState, useTransition} from 'react';
...
let [isPending, startTransition] = useTransition();
...
<div>
<input
onChange={e => {
startTransition(() => {
setName(e.target.value);
})
}}
/>
;{
a.map(() => {
return <div>{name}</div>
})
}
</div>
위와 같이 문제를 일으키는 state 변경함수를 startTransition으로 감싸준다.
startTransition의 원리
코드 시작 시점을 뒤로 늦춰준다.다른 작업을 먼저하고
1. a를 input에 보여주기
2. 그 후 div 에 넣어준다.
늦게처리를 도와주는 것이기 때문에 한꺼번에 작업해준다.
- isPending은 언제쓰냐 startTransition이 처리중일 때 true가 되는 함수임
이걸 써서 로딩중이라고 말할 수 있다.
useDefferedValue
이걸 써도 느린 컴포넌틑 성능 향상 가능
let state = useDefferedValue(name)
name 이란 애가 변경할 때마다 늦게 처리를 해준다.