useTransition 본문
반응형
useTransition
개념 및 사용법
useTransition
은 UI를 차단하지 않고 state를 업데이트할 수 있는 React 훅입니다.useTransition
은 정확히 두 개의 항목이 있는 배열을 반환합니다:- 보류 중인 트랜지션이 있는지 여부를 알려주는
isPending
플래그 - state 업데이트를 트랜지션으로 표시할 수 있는
[startTransition
함수] (아무것도 return 하지 않음)
- 보류 중인 트랜지션이 있는지 여부를 알려주는
- 사용법
function TabContainer() {
const [isPending, startTransition] = useTransition();
const [tab, setTab] = useState('about');
function selectTab(nextTab) {
startTransition(() => {
setTab(nextTab);
});
}
// ...
}
주의사항
- 해당 state의
set
함수에 접근할 수 있는 경우에만 업데이트를 트랜지션으로 감쌀 수 있습니다. 일부 prop이나 커스텀 훅 값에 대한 응답으로 트랜지션을 시작하려면, 대신[useDeferredValue]
를 사용해보세요. startTransition
에 전달하는 함수는 동기식이어야 합니다. React는 이 함수를 즉시 실행하여, 실행하는 동안 발생하는 모든 state 업데이트를 트랜지션으로 표시합니다. 나중에 더 많은 state 업데이트를 수행하려고 하면(예: 타임아웃), 트랜지션으로 표시되지 않습니다.- 트랜지션으로 표시된 state 업데이트는 다른 state 업데이트에 의해 중단됩니다. 예를 들어, 트랜지션 내에서 차트 컴포넌트를 업데이트한 다음, 차트가 다시 렌더링되는 도중에 입력을 시작하면 React는 입력 업데이트를 처리한 후 차트 컴포넌트에서 렌더링 작업을 다시 시작합니다.
- input을 제어하는 state 변수에는 트랜지션을 사용할 수 없습니다.
사용법
- TabButton의 onClick함수를 startTransition으로 감싸서 사용자 상호작용을 차단하지 않습니다.
- post탭을 클릭하고 바로 contact탭을 클릭해보세요 앱이 중단되지 않습니다.
- startTransition을 제거하고 한번 테스트 해보세요, posts탭이 눌렸다고 사용자는 알 수 없습니다.
- isPending 변수는 transition이 진행중인가를 알려줍니다.
- useTransition.tsx
import AboutTab from "@/components/AboutTab";
import ContactTab from "@/components/Contact";
import PostsTab from "@/components/Posts";
import TabButton from "@/components/TabButton";
import { useState } from "react";
export default function TabContainer() {
const [tab, setTab] = useState("about");
return (
<>
<TabButton isActive={tab === "about"} onClick={() => setTab("about")}>
About
</TabButton>
<TabButton isActive={tab === "posts"} onClick={() => setTab("posts")}>
Posts (slow)
</TabButton>
<TabButton isActive={tab === "contact"} onClick={() => setTab("contact")}>
Contact
</TabButton>
<hr />
{tab === "about" && <AboutTab />}
{tab === "posts" && <PostsTab />}
{tab === "contact" && <ContactTab />}
</>
);
}
- TabButton.tsx
import { useTransition } from "react";
type TabButtonProps = {
children: React.ReactNode;
isActive: boolean;
onClick: () => void;
};
export default function TabButton({
children,
isActive,
onClick,
}: TabButtonProps) {
const [isPending, startTransition] = useTransition();
if (isActive) {
return <b>{children}</b>;
}
if (isPending) {
return <b className="pending">{children}</b>;
}
return (
<button
onClick={() => {
startTransition(() => {
onClick();
});
}}
>
{children}
</button>
);
}
- AboutTab.tsx
export default function AboutTab() {
return <p>Welcome to my profile!</p>;
}
- Posts.tsx
import { memo } from "react";
const PostsTab = memo(function PostsTab() {
// 한 번만 기록합니다. 실제 속도저하는 SlowPost 내부에서 이뤄집니다.
let items = [];
for (let i = 0; i < 500; i++) {
items.push(<SlowPost key={i} index={i} />);
}
return <ul className="items">{items}</ul>;
});
function SlowPost({ index }: { index: number }) {
let startTime = performance.now();
while (performance.now() - startTime < 1) {
// 매우 느린 코드를 구현하기 위해 항목마다 1ms동안 아무것도 하지 않도록 합니다
}
return <li className="item">Post #{index + 1}</li>;
}
export default PostsTab;
- Contact.tsx
export default function ContactTab() {
return (
<>
<p>You can find me online here:</p>
<ul>
<li>admin@mysite.com</li>
<li>+123456789</li>
</ul>
</>
);
}
출처
반응형
'React' 카테고리의 다른 글
React 배너 슬라이더 만들기 + touch evnet (3) | 2024.01.04 |
---|---|
useDefferedValue (1) | 2023.10.03 |
RTK Query 캐쉬 무효화 (0) | 2023.10.03 |
Comments