React Version 18
2023. 1. 31. 21:29ㆍ프로그래밍/React
- 목차
Automatic batching
업데이트 대상이 되는 상태값들을 하나의 그룹으로 묶어서
한 번의 리렌더링에 업데이트가 모두 진행될 수 있게 해주는 것
한 함수 안에서 setState를 여러 번 호출시켜도 리렌더링은 단 한번만 발생함
함수의 끝에서 업데이트가 되며 여러 번 리렌더링 하는 것을 막기 때문에 성능에 좋은 영향을 줌
function handleClick() {
setCount(c => c + 1); // 리렌더링 X
setFlag(f => !f); // 리렌더링 X
// 마지막에 한 번만 리렌더링함
}
batch 처리 해제
import { flushSync } from "react-dom";
function handleClick() {
flushSync(() => {
setCount(count + 1);
));
// 리렌더링
flushSync(() => {
setClicked(true);
});
// 리렌더링
}
Suspense on the server
리액트의 서버 사이드 렌더링
- 서버에서 전체 앱에 대한 데이터를 가져옴
- 서버에서 전체 앱을 HTML으로 렌더링하고 응답으로 보냄
- 클라이언트에서 전체 앱에 대한 JS 코드를 로드함
- 클라이언트에서 JS 논리를 전체 앱에 대해 서버 생성 HTML에 연결함
문제점
다음 단계가 시작되기 전에 각각의 단계가 한 번에 완료되어야 함
앱의 일부가 다른 부분보다 느릴 경우 효율적이지 않음
(먼저 생성된 컴포넌트가 생성중인 다른 컴포넌트를 위해 계속 기다려야 함)
Suspense
<Suspense />를 사용해 앱을 더 작은 독립 단위로 나눌 수 있음
사용자가 컨텐츠와 더욱 빠르게 상호작용 할 수 있음
생성이 완료된 컴포넌트는 보여지고, 아직 생성중인 컴포넌트는 fallback에 정의된 컴포넌트를 보여줌
<div>
<Navbar />
<Suspense fallback={<Spinner />}>
<Sidebar />
</Suspense>
<Suspense fallback={<Spinner />}>
<Post />
</Suspense>
<Suspense fallback={<Spinner />}>
<Comment />
</Suspense>
</div>
Transition
상태 업데이트에 우선순위를 줄 수 있음
startTransition이 적용된 업데이트는 긴급하지 않은 것으로 처리되며
다른 긴급한 업데이트가 필요한 경우 중단됨
예시)
검색 창 (Urgent Update)
- 버튼 클릭, 키보드 입력과 같이 업데이트가 즉시 일어나야 하는 상태 값들을 대상으로 함
결과 창 (Transition Update)
- 사용자가 상태 값의 변화에 따른 업데이트가 즉시 일어나는 것을 기대하지 않음
import { startTransition } from 'react';
// Urgent
setInputValue(input);
startTransition(() => {
// Secondary
setSearchQuery(input);
});
Transition이 보류 중일 때
우선순위가 밀려서 업데이트 보류가 일어날 경우
useTransition을 사용해 isPending 값을 가져와서 로딩 컴포넌트 보여주기
import { useTransition } from 'react';
const [isPending, startTransition] = useTransition();
...
{isPending && <Spinner />}
startTransition 대신 업데이트 보류하는 방법
- State 를 두 개로 나누어 다르게 처리함
- debounce 이용
- setTimeout 이용
React Version 18로 업그레이드
1. react, react-dom 설치
npm install react react-dom
2. ReactDOM.render ==> ReactDOM.createRoot 로 변경
ReactDOM.render(<App />, document.querySelector("#root"));
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<App />);