The useTransition
hook in React helps manage the prioritization of state updates. It allows you to mark certain updates as non-urgent, so they can be deferred to keep the UI responsive. This is particularly useful for heavy updates that might otherwise slow down the user interface.
How useTransition
Works
- Initial Setup: You call
useTransition
to get two values:isPending
andstartTransition
. - Marking Updates: Use
startTransition
to wrap state updates that can be deferred. - Pending State:
isPending
is a boolean that indicates if a transition is ongoing.
Examples
Here are five examples to illustrate how useTransition
can be used:
- Filtering a List
import { useState, useTransition } from 'react';
function FilterList({ items }) {
const [query, setQuery] = useState('');
const [filteredItems, setFilteredItems] = useState(items);
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
startTransition(() => {
setFilteredItems(items.filter(item => item.includes(value)));
});
};
return (
<div>
<input type="text" value={query} onChange={handleChange} />
{isPending && <div>Loading...</div>}
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
- Sorting a Table
import { useState, useTransition } from 'react';
function SortableTable({ data }) {
const [sortKey, setSortKey] = useState('name');
const [sortedData, setSortedData] = useState(data);
const [isPending, startTransition] = useTransition();
const handleSort = (key) => {
setSortKey(key);
startTransition(() => {
setSortedData([...data].sort((a, b) => a[key].localeCompare(b[key])));
});
};
return (
<div>
<button onClick={() => handleSort('name')}>Sort by Name</button>
<button onClick={() => handleSort('age')}>Sort by Age</button>
{isPending && <div>Sorting...</div>}
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{sortedData.map((item, index) => (
<tr key={index}>
<td>{item.name}</td>
<td>{item.age}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
- Loading More Items
import { useState, useTransition } from 'react';
function LoadMoreList({ initialItems }) {
const [items, setItems] = useState(initialItems);
const [isPending, startTransition] = useTransition();
const loadMore = () => {
startTransition(() => {
fetch('/api/more-items')
.then(response => response.json())
.then(newItems => setItems([...items, ...newItems]));
});
};
return (
<div>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={loadMore} disabled={isPending}>
{isPending ? 'Loading...' : 'Load More'}
</button>
</div>
);
}
- Updating a Chart
import { useState, useTransition } from 'react';
function Chart({ data }) {
const [chartData, setChartData] = useState(data);
const [isPending, startTransition] = useTransition();
const updateChart = (newData) => {
startTransition(() => {
setChartData(newData);
});
};
return (
<div>
<button onClick={() => updateChart(generateNewData())}>
Update Chart
</button>
{isPending && <div>Updating...</div>}
<ChartComponent data={chartData} />
</div>
);
}
- Navigating Between Tabs
import { useState, useTransition } from 'react';
function Tabs({ tabs }) {
const [activeTab, setActiveTab] = useState(tabs[0]);
const [isPending, startTransition] = useTransition();
const handleTabClick = (tab) => {
startTransition(() => {
setActiveTab(tab);
});
};
return (
<div>
<div className="tab-buttons">
{tabs.map((tab, index) => (
<button key={index} onClick={() => handleTabClick(tab)}>
{tab}
</button>
))}
</div>
{isPending && <div>Loading...</div>}
<div className="tab-content">
{activeTab}
</div>
</div>
);
}
Practice Exercises
Here are five practice exercises to help you get comfortable with useTransition
:
- Exercise 1: Create a search bar that filters a list of products. Use
useTransition
to defer the filtering operation. - Exercise 2: Implement a pagination system for a list of articles. Use
useTransition
to handle the loading of new pages. - Exercise 3: Build a dynamic form where adding new fields triggers a state update. Use
useTransition
to manage the addition of new fields. - Exercise 4: Develop a dashboard with multiple widgets. Use
useTransition
to update the data in the widgets without blocking the UI. - Exercise 5: Create a to-do list application where marking tasks as completed triggers a state update. Use
useTransition
to handle the update smoothly.
These exercises should help you get a good grasp of how to use the useTransition
hook in various scenarios.