useTransition Hook
useTransition Hook — UI-ի թարմացում առանց UI-ի դանդաղեցման
useTransition-ը React 18-ի hook է, որը թույլ է տալիս React-ին տարբերակել՝ որ թարմացումները կարևոր (urgent) են, իսկ որոնք՝ ոչ այնքան կարևոր (non-urgent)։ Այսպիսով React-ը կարող է առաջնահերթություն տալ այն թարմացումներին, որոնք անմիջապես ազդում են օգտվողի փորձի վրա։
Օրինակ՝ օգտվողը գրում է search input-ում։ React-ը պետք է միաժամանակ․ 1️⃣ Թարմացնի input-ի արժեքը (urgent) 2️⃣ Ֆիլտրի հարյուրավոր տվյալներ ցուցակի մեջ (non-urgent)
Առանց useTransition-ի՝ input-ը կարող է “սառել” կամ ուշ արձագանքել։ useTransition-ը լուծում է հենց այս խնդիրը։
const [isPending, startTransition] = useTransition();
import React, { useState, useTransition } from 'react';
export default function SearchList() {
const [query, setQuery] = useState('');
const [filtered, setFiltered] = useState([]);
const [isPending, startTransition] = useTransition();
const items = Array.from({ length: 5000 }, (_, i) => `Element ${i + 1}`);
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
startTransition(() => {
const filteredItems = items.filter((item) =>
item.toLowerCase().includes(value.toLowerCase())
);
setFiltered(filteredItems);
});
};
return (
<div>
<h2>🔎 Ֆիլտրման օրինակ useTransition-ով</h2>
<input
type="text"
value={query}
onChange={handleChange}
placeholder="Փնտրիր..."
/>
{isPending && <p>Լիցքավորում...</p>}
<ul>
{filtered.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
}
Այստեղ React-ը input-ի արժեքը թարմացնում է անմիջապես, իսկ ցուցակի filtering-ը կատարում է transition-ի շրջանակում՝ առանց UI-ի “սառելու”։ Եթե ֆիլտրման գործընթացը տևում է մի փոքր երկար, React-ը պահում է input-ի թարմացումը՝ անտեսանելի latency-ով։
setQuery() — կատարվում է անմիջապես՝ urgent updatestartTransition() — սկսում է non-urgent update (filtering)isPending true է՝ մինչև filtering-ը ավարտվի`isPending` արժեքը կարող ես օգտագործել՝ ցուցադրելու համար loader կամ skeleton։
{isPending ? (
<p>Դիտակը նոր տվյալներ է բեռնում...</p>
) : (
<List data={filtered} />
)}
Այնպես React-ը կարող է smoother ձևով փոխել տվյալները՝ առանց տեսանելի ցնցման։
Այս hook-ը նաև հիանալի է pagination-ի կամ tab-switching-ի դեպքում, երբ նոր էջի բովանդակությունը պետք է բեռնվի առանց UI-ի կարճ freeze-ի։
import React, { useState, useTransition } from 'react';
export default function PaginationExample() {
const [page, setPage] = useState(1);
const [isPending, startTransition] = useTransition();
const handlePageChange = (newPage) => {
startTransition(() => {
setPage(newPage);
});
};
return (
<div>
<h3>Էջ {page}</h3>
<button onClick={() => handlePageChange(page - 1)} disabled={page === 1}>
Նախորդ
</button>
<button onClick={() => handlePageChange(page + 1)}>
Հաջորդ
</button>
{isPending && <p>Բեռնում է հաջորդ էջը...</p>}
</div>
);
}
Այստեղ UI-ն երբեք չի “սառչում” էջերի միջև անցնելիս։ React-ը նախ ցուցադրում է գործողության արդյունքը, հետո սկսում non-urgent update։
React-ը իրականացնում է Concurrent Rendering՝ թույլ տալով միաժամանակ ունենալ երկու rendering գործընթաց՝ մեկը առաջնահերթ (urgent), մյուսը՝ հետին պլանում (deferred)։ Այն “կասեցնում է” non-urgent rendering-ը, եթե նոր urgent գործողություն տեղի ունենա։
Սա React-ի մեծ նորարարություններից մեկն է, որը թույլ է տալիս գրել responsive UI՝ առանց հավելյալ throttling կամ debounce logic-ի։
Գրիր կոմպոնենտ, որը․
Փորձիր տարբերությունը առանց useTransition-ի և տես՝ input-ը ինչպես է արձագանքում։ Արդյունքը ակնհայտ է 💨։
[isPending, startTransition]։