React in 2026 is significantly different from React in 2020. Server Components, Suspense for data fetching, concurrent rendering, and useTransition have changed how applications are structured. Senior frontend interviews probe whether you understand these new patterns and when to use them.
The hooks foundation (still essential)
useState— local stateuseEffect— side effects after renderuseRef— mutable ref + DOM refuseMemo/useCallback— referential stability and memoizationuseContext— read contextuseReducer— complex local state
Common bugs:
- Stale closures in useEffect (missing deps array entries)
- Recreating functions on every render breaking memoization
- Using useEffect for derived state when computed inline would do
Concurrent React
React 18+ introduced concurrent rendering. The renderer can interrupt itself and prioritize urgent updates.
useTransition
Mark a state update as non-urgent. The renderer can pause it if more important work arrives.
const [isPending, startTransition] = useTransition();
const handleSearch = (query) => {
startTransition(() => {
setSearchResults(filterResults(query));
});
};
Use case: filtering a large list while user keeps typing.
useDeferredValue
Returns a “previous value” version of a value that lags behind the urgent value. Lets the urgent UI (input) stay responsive while the deferred UI (results) catches up.
Suspense for data fetching
The component “suspends” by throwing a promise. The closest Suspense boundary catches it and renders a fallback. When the promise resolves, the component renders.
Libraries: React Query, Relay, and Next.js have Suspense-compatible data fetching. Manual fetching also possible via experimental use() hook.
Server Components (RSC)
Components that run on the server and stream their HTML to the client. Benefits:
- Zero JavaScript for the component itself in the client bundle
- Direct database access from the component
- Smaller client bundles
- Better performance for content-heavy sites
Tradeoffs:
- Cannot use state, effects, or browser APIs
- Cannot have event handlers
- Mental model shift — you think about what runs where
Mainstream via Next.js App Router as of 2024. Other frameworks (Remix, future Tanstack Start) are following.
Client Components (the “use client” boundary)
Components that need state, effects, or interactivity. Marked with "use client" at the top of the file. Bundled to the client.
The boundary between server and client matters. Best practice: keep client components small and leaf-like; render most content server-side.
Streaming and progressive rendering
With Server Components + Suspense, parts of the page can stream to the client before others are ready. The user sees content faster, even on slow APIs.
State management in 2026
The ecosystem has consolidated:
- Server state: React Query / TanStack Query, SWR, Apollo. Caches, retries, mutations, optimistic updates.
- Client state: Zustand (small apps), Redux Toolkit (large apps), Jotai (atomic, fine-grained).
- URL state: Next.js App Router primitives, react-router, nuqs (typed query params).
- Form state: React Hook Form, Formik, native form actions in RSC.
Common antipatterns
- useState + useEffect to fetch data — use a real data library
- useMemo on every value — adds overhead, often net-negative
- Context for everything — re-renders cascade; use Zustand or selectors
- useEffect to derive state from props — compute inline instead
Frequently Asked Questions
Should I use Server Components for everything?
Use them as the default. Drop into Client Components only when interactivity, state, or browser APIs are needed. Keep client boundaries small.
Is Redux still relevant?
Redux Toolkit is excellent for large applications with complex shared state. For most new apps, Zustand or Jotai is simpler. The “default Redux for everything” era is over.
What is the difference between useTransition and useDeferredValue?
useTransition wraps a state setter; useDeferredValue wraps a value. Functionally similar; use whichever fits the call site.