React 18 shipped in March 2022 after two years of work, bringing the concurrent features that the React team has been building toward since React 16’s Fiber rewrite in 2017. The key promise: React can now interrupt, pause, and resume rendering work — allowing urgent updates (typing, clicking) to take priority over slow background updates (data fetching, large list renders).
Upgrading to React 18
The one-line change: replace ReactDOM.render() with ReactDOM.createRoot():
// React 17
ReactDOM.render(<App />, document.getElementById('root'));
// React 18
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
Automatic Batching
In React 17, state updates inside event handlers were batched, but updates inside setTimeout, Promise, and native event handlers triggered a separate render per setState. React 18 batches all updates everywhere by default — reducing unnecessary re-renders.
useTransition: Marking Updates as Non-Urgent
const [isPending, startTransition] = useTransition();
function handleSearch(value) {
setInputValue(value); // urgent — update immediately
startTransition(() => {
setFilteredList(filterItems(allItems, value)); // non-urgent — can be deferred
});
}
React prioritises the urgent setInputValue update (keeps the input responsive) and processes the expensive filter in the background. isPending lets you show a loading indicator during the transition.
useDeferredValue
For values you don’t control (e.g., from a parent component), useDeferredValue provides a deferred copy that updates less urgently than the original:
const deferredQuery = useDeferredValue(query);
// deferredQuery lags behind query during fast typing — prevents expensive re-renders
Suspense Improvements
React 18 makes Suspense work with server-side rendering via the new renderToPipeableStream API. Content can stream to the browser as it becomes ready, dramatically improving Time to First Byte for server-rendered apps.
Strict Mode Changes
React 18 Strict Mode intentionally mounts components twice in development to surface bugs from non-idempotent effects. If you see effects running twice in dev, that’s working as designed — ensure your useEffect cleanup functions properly undo their setup.
React 18 is a significant release, but the upgrade path is smooth — most apps just need the createRoot change and minor Strict Mode bug fixes. The concurrent features unlock a tier of UI responsiveness that was previously only achievable with significant custom optimisation work.