리액트 공식 문서(react.dev) 읽기
Built-in React Hooks
1. useTransition
📍참고
https://react.dev/reference/react/useTransition
📍원치 않는 로딩 UI 방지하기
Suspense 컴포넌트의 fallback을 활용해 로딩 UI를 만들 수 있다- 그런데, 로딩 UI가 전체 UI 를 다 가리고 표현되면 유저 경험을 해치게 된다
UI를 변경하는 동작을 startTransiton으로 래핑하면, 이 동작은 기존 UI를 blocking하지 않는다
📍suspense 가능한 router 구축
React 팀에서는 React 프레임워크를 만들거나, router를 만들 때 페이지 네비게이션을 transition으로 만들라고 권장하고 있다
function Router() {
const [page, setPage] = useState('/');
const [isPending, startTransition] = useTransition();
function navigate(url) {
startTransition(() => {
setPage(url);
});
}
// ...
그 이유는,
✅transition은 중단 가능하기 때문에, 리렌더링이 끝날 때까지 기다리지 않고 UI를 전환할 수 있기 때문이다
또한 원치 않는 loading indicator(예 - suspense의 fallback)를 isPending으로 취소할 수 있다
예를 들면,
- UI 전환을 transition으로 만들었을 경우,
- 렌더링이 오래 걸리는 탭을 눌렀는데, 다른 탭을 눌러서 loading indicator를 빠져나올 수 있다
페이지 전환을 transition으로 처리하여 전체 UI를 막아버리는 loading indicator를 방지하는 예제
https://react.dev/reference/react/useTransition#building-a-suspense-enabled-router
⭐Suspense 가능 라우터는기본적으로 페이지 네비게이션을 transition으로 래핑해야 한다
📍트러블슈팅 : 자주 등장하는 에러
✅1. input value 업데이트를 transition으로 처리하면 안된다
- transition이 non-blocking이기 때문
✅2. startTransition 함수로 래핑해야 한다
bad case1
startTransition(() => {
// ❌ Setting state *after* startTransition call
setTimeout(() => {
setPage('/about');
}, 1000);
});
이렇게 바꿔야 한다
setTimeout(() => {
startTransition(() => {
// ✅ Setting state *during* startTransition call
setPage('/about');
});
}, 1000);
bad case2
startTransition(async () => {
await someAsyncFunction();
// ❌ Setting state *after* startTransition call
setPage('/about');
});
이렇게 바꿔야 한다
await someAsyncFunction();
startTransition(() => {
// ✅ Setting state *during* startTransition call
setPage('/about');
});