React ships a rendering layer and little else. This guide helps you compare eight widely used React libraries across UI, state, routing, data fetching, forms, animation, and authentication. It covers verified versions, bundle sizes, survey adoption, and React 19 status, and shows where each library sits next to a Strapi 5 backend.
React 19.3.0 is the current stable release, per the React versions page, and the React Compiler reached its first stable 1.0.0 release in October 2025, when the React team wrote that "New apps should use React Compiler" in the compiler announcement. Server Components are stable, and useActionState and useOptimistic shipped with React 19, and concurrent APIs like useTransition and Suspense are stable. If you plan to use these features, your supporting libraries need to account for that model.
React still only renders UI. You bring in libraries for routing, server state, forms, animation, and authentication, and each choice affects bundle size, type safety, and how content moves from your API to the screen. This guide helps you pick React libraries for content-driven apps, whether you are building an ecommerce storefront, a SaaS dashboard, or a marketing site fed by a headless CMS.
In brief:
- The guide covers eight React libraries across UI components, state management, routing, data fetching, forms, animation, and authentication, each with its current version and minimum requirements.
- React 19 and Server Components compatibility, TypeScript support, bundle size, and State of React 2025 adoption data drove the selection.
- Several libraries are now on newer major versions: Material UI is on version 9, React Router is on version 8, and Framer Motion is now Motion.
- Each entry ends with how the library fits a Strapi 5 backend, including which Strapi features are on by default, need configuration, or require a plugin.
How React Libraries Fit a React 19 Application
You add React libraries to your component tree through hooks, components, or providers. Libraries that support React Server Components can keep data-fetching logic on the server so it never ships to the client bundle. Libraries built around client-side hooks, including state stores, animation, and forms, run in Client Components only.
Use four checks when comparing the libraries below. First, confirm that peer dependencies explicitly declare React 19 support rather than merely implying it. Then look for a documented TypeScript minimum and a measurable Bundlephobia size. Finally, check adoption in the State of React 2025 survey, which collected 3,760 responses between November 2025 and January 2026.
1. Material UI (MUI): Prebuilt Components on Material Design
Material UI is at version 9.4.0, and there was no version 8. MUI's introduction post states: "Material UI moves from v7 straight to v9 (there is no Material UI v8, like there is no v2), in step with MUI X v9." The supported platforms page lists React ^17.0.0 and TypeScript 4.9 as minimums, with React 19 in the peer range.
If adoption matters to your decision, MUI is the most used UI library in the State of React 2025 results: 57.2% of respondents use it, with 34.3% positive and 7.8% negative sentiment. The GitHub repo has about 99k stars, and @mui/material pulls roughly 7.2 million weekly npm downloads.
If you need styling isolation, the enableCssLayer option wraps MUI styles in a CSS cascade layer. You can use either <StyledEngineProvider enableCssLayer> or <AppRouterCacheProvider options={{ enableCssLayer: true }}> in Next.js, per the CSS layers docs. One caution: Pigment CSS, the zero-runtime engine previewed in 2024, is still alpha, and MUI's 2026 roadmap post says "development is paused." It is better not to plan a migration around it.
Trade-offs: consider dependency weight alongside copy-paste alternatives (shadcn/ui scored 32.7% positive sentiment in the State of React survey), and the Material look does not suit every brand.
With Strapi: MUI fits the community integration for admin dashboards and SaaS interfaces that read content from Strapi's APIs. The React integration page covers the wiring; MUI components render client-side while a Server Component or TanStack Query handles the fetch from the Strapi REST API.
2. Redux Toolkit: Centralized State With RTK Query
Redux Toolkit is at version 2.12.0. If you are considering RTK 2.x, account for its TypeScript 5.4+ requirement and React 18 requirement through React-Redux version 9, per the RTK 2 migration guide. Bundlephobia measures the package at 13.3 kB minified and gzipped, of which Immer accounts for 28.1%. The 2.11.0 release moved to Immer version 11, and RTK Query's stress-test benchmark showed about 30% less scripting time versus Immer 10.1.
RTK Query, the bundled data layer, uses providesTags and invalidatesTags for automated refetching. When your components share a queryCacheKey, RTK Query deduplicates their requests. It removes unused cache entries 60 seconds after the last subscription ends, per the cache behavior docs. The current release also includes infinite queries via build.infiniteQuery() and polling with skipPollingIfUnfocused. configureStore connects to Redux DevTools automatically and exposes a dedicated RTK Query panel. Adding RTK Query costs about 9 kB plus 2 kB for React hooks on top of RTK, per the RTK Query overview.
Trade-offs: 33.8% of State of React 2025 respondents use it, but only 11.8% expressed positive sentiment, the lowest in this list. The slice architecture takes time to learn, and 13.3 kB is a lot for an app with modest global state.
With Strapi: RTK Query endpoints map cleanly to Strapi's REST routes. If you are deciding between REST and the GraphQL plugin, the REST and GraphQL comparison for Strapi 5 walks through the trade-offs.
3. React Router: Routing With Loaders, Actions, and Framework Mode
React Router is at version 8.3.1. Before upgrading, note that the changelog lists Node 22.22.0+, React 19.2.7+, and Vite 7+ as 8.0.0 requirements. You still have two active maintenance branches: 7.18.3 and 6.30.6, per the releases page. Since version 7, react-router-dom is no longer a separate package. You import from react-router and DOM-specific APIs from react-router/dom, per the upgrade guide.
The modes documentation gives you three modes to choose from. Declarative uses BrowserRouter for URL-to-component matching. Data uses createBrowserRouter with RouterProvider and adds loader, action, and useFetcher. Framework mode runs through the Vite plugin with the Route Module API, type-safe href, code splitting, and a choice of SPA, SSR, or static rendering. SPA is a rendering strategy inside Framework mode, not a mode itself. Since 7.0.0, React Router has generated route types into .react-router/types/, per the type safety explanation. Middleware stabilized in 7.9.0 behind the future.v8_middleware flag, per the middleware announcement.
Do not plan around Server Components support yet. The RSC guide says it is "experimental and subject to breaking changes in minor/patch releases," and the server APIs carry unstable_ prefixes.
The Remix story: "What we planned to release as Remix v3 is now going to be released as React Router v7," per the merger announcement. Remix 3 is now a separate project described as "a reimagining of what a web framework can be" in the Wake up, Remix post, and no stable release is confirmed.
Trade-offs: three modes mean three mental models, and SEO in a client-only SPA is an additional planning consideration, including whether to use prerendering or SSR.
With Strapi: you can use loaders to fetch Strapi content before render so route components receive data as props. The React Router 7 integration page and the React 19 blog tutorial with Strapi 5 show how your frontend code can generate routes from a content model. For the migration backstory, the migration guide covers what changed.
4. TanStack Query: Server State With Stale-While-Revalidate Caching
@tanstack/react-query is at version 5.102.8. For React, stay on version 5: there is no React adapter version 6. Version 6 exists only for Solid and Svelte, per the migration guide. The React adapter requires React 18+ and TypeScript 5.6+.
Watch one default in particular. Per the important defaults page, staleTime is 0, so every mount triggers a background refetch, and gcTime is five minutes. Set staleTime explicitly for navigation, user profiles, and other slow-changing content. For data that never changes during a session, consider staleTime: 'static'; the docs recommend it for feature flags and reference tables. Structural sharing is on by default, so components re-render only when referenced data changes.
For Suspense, version 5 gives you stable useSuspenseQuery, useSuspenseInfiniteQuery, and useSuspenseQueries APIs. useSuspenseQuery guarantees data is defined, per its reference page. Two useSuspenseQuery calls in one component suspend serially, so use useSuspenseQueries for parallel fetches. For SSR, you can prefetch on the server, dehydrate, and wrap with HydrationBoundary. Since 5.40.0, you can stream pending queries without awaiting every prefetch, per the advanced SSR guide. The devtools are only bundled when NODE_ENV === 'development', with an opt-in production import from @tanstack/react-query-devtools/production.
Trade-offs: cache invalidation across hierarchical query keys gets complex in large apps, and the library is unnecessary if you fetch everything in Server Components. TanStack DB, which plugs into existing useQuery calls, is still pre-1.0 at version 0.6.
With Strapi: query keys map naturally to built-in Collection Types. The editorial calendar tutorial with TanStack Start and Strapi 5 demonstrates optimistic updates against Strapi endpoints.
5. Zustand: Client State in Under Half a Kilobyte
Zustand is at version 5.0.15 and weighs 489 B minified and gzipped, which Bundlephobia puts at 27.8 times smaller than Redux Toolkit. If you add it to your stack, it requires TypeScript 4.5+ and React 18, per the migration guide. The npm download API reported about 50.7 million downloads for the week ending 5 August, per the npm downloads endpoint.
The State of React 2025 state management results call Zustand "the most popular in terms of user satisfaction" and say it "should be considered the leader in this category." You also get six official middlewares, per the reference docs: persist, devtools, subscribeWithSelector, immer, redux, and combine. The devtools middleware needs @redux-devtools/extension installed, and the immer middleware needs the immer package.
Trade-offs: you do not get built-in time-travel debugging without the devtools middleware, and the library provides less structure for very large teams. Zustand's Next.js guide also warns against reading or writing the store from Server Components. No authoritative source supports the oft-quoted sub-millisecond re-render figures.
With Strapi: keep Zustand for UI state and preferences, while TanStack Query or Server Components own server data. The persist middleware is a clean place to store a visitor's locale choice when you use Strapi's built-in internationalization feature, covered in the multilingual website guide and the Strapi 5 i18n guide.
6. Motion (Formerly Framer Motion): Declarative Animation
Framer Motion is now Motion for React, at version 13.2.0. You install motion and import from "motion/react"; the npm page reads "Framer Motion is now Motion. Import from motion/react instead of framer-motion." The installation docs set React 18.2 as the minimum, and the peer dependency range is react: ^18.0.0 || ^19.0.0, so React 19 is fully supported.
The API is still initial, animate, and exit props, AnimatePresence for exit animations, layoutId for shared element transitions, and built-in gestures for hover, tap, focus, drag, and in-view.
You do not need to build reduced-motion handling from scratch. The accessibility guide covers the reducedMotion option and useReducedMotion hook. MotionConfig accepts reducedMotion="user" (follow the OS setting), "always", or "never", and the default is "never", so you need to opt in. When reduced motion is active, "transform and layout animations will be disabled. Other animations, like opacity and backgroundColor, will persist." That behavior maps to WCAG 2.2 SC 2.3.3.
Trade-offs: added bundle weight on performance-sensitive pages, and gesture-heavy interactions take iteration to get right.
With Strapi: product cards from a community Shopify integration or article teasers fetched from built-in Strapi Collection Types can animate in with staggered variants. If your pages use built-in Dynamic Zones, the guide on type-safe rendering for Dynamic Zones shows how to type the components you will be animating.
7. React Hook Form: Forms Without Per-Keystroke Re-renders
React Hook Form is at version 7.88.0. It registers inputs through refs as uncontrolled components, so typing does not fire a state update on every keystroke. Bundlephobia measures it at 14.1 kB minified and gzipped, and npm shows about 40.6 million weekly downloads. If you are comparing form libraries, State of React 2025 recorded 1,964 respondents using React Hook Form versus 1,095 for Formik and 567 for TanStack Form, per the component libraries results.
Do not move to version 8 without planning for a pre-release. The latest is 8.0.0-beta.3, per the releases page. The migration guide describes the main break: "The internal render identifier has been renamed from id to key. The keyName option has been removed from useFieldArray. The render key is always key."
For validation, use @hookform/resolvers with Zod, Yup, or another supported schema library. Zod is at version 4.6.5 with roughly 274.7 million weekly downloads, and its version 4 docs list a 5.36 kB gzipped core and a 1.88 kB Mini variant.
Trade-offs: the widely shared load-time benchmark (3,800 ms versus 5,800 ms for Formik) comes from the performance-compare repo, which has been archived since 2020 and ran under a 6x CPU throttle. It is useful as history, not current data. Multi-step forms and conditional validation still take work.
With Strapi: your frontend form submission code can create or update entries by sending requests through Strapi's REST API, and frontend Zod schemas can mirror your Strapi Content-Types. Strapi's custom fields are built in and free, but third-party field types require installing their plugin from the Marketplace.
8. Auth.js (NextAuth.js): Authentication for Next.js and React
Auth.js version 5 is still in beta. The integrations page labels next-auth as "v5 (beta) and v4 (maintenance mode)," with 5.0.0-beta.32 as the latest beta and 4.24.15 as the latest stable. If you choose version 5, install it with npm install next-auth@beta; there is no announced GA date.
The OAuth docs say "Auth.js comes with over 80 providers preconfigured," though only about 20 are actively tested. OAuth, magic links, and credentials are stable. The WebAuthn docs mark passkeys as experimental and "not recommended for production use."
You can choose between two session strategies: JWT in an HttpOnly cookie, the default without a database adapter, or database sessions, the default with one. In version 5, JWTs are encrypted with A256CBC-HS512, per the JWT reference; A256GCM applies to version 4 only.
For security, Auth.js documents the double-submit cookie CSRF pattern in the core types reference. The security page also commits: "We will respond to your report within 72 hours. If the issue is confirmed, we will release a patch as soon as possible. If 90 days have elapsed and we still don't have a fix, we will disclose the issue publicly." Security patches ship only for the latest tag.
Trade-offs: it is built around Next.js; other React setups need more wiring. Migrating from version 4 means reviewing a substantial rewrite.
With Strapi: Auth.js owns its frontend session layer, but Strapi does not automatically recognize that session. You need to send credentials or exchange or map the Auth.js identity to a Strapi-recognized authentication mechanism; Strapi then applies the configured API roles and permissions. Strapi's Users and Permissions feature is available by default but needs configuration; it ships Public and Authenticated roles and two JWT modes (legacy-support and refresh) set in /config/plugins. The authentication guide covers the handoff.
How to Use React Libraries With Strapi 5
Strapi 5 exposes a REST API by default for every Content-Type, and a GraphQL endpoint once you install the package described in the GraphQL plugin docs. If you are adapting code from a version 4 tutorial, watch for three Strapi 5 differences. Responses are flat, so fields sit directly on data rather than under data.attributes.
Documents use a string documentId, not an integer id. And per the REST docs, "All content types are private by default and need to be either made public or queries need to be authenticated with the proper permissions."
Strapi owns content modeling, content APIs, and configured backend authorization. Your frontend owns rendering, routing, forms, client state, validation, and forwarding authentication credentials. Auth.js owns its separate session layer unless you implement a Strapi-recognized handoff, while Strapi Cloud provides managed hosting only when that hosting product is selected.
Here is a TanStack Query hook against a Strapi 5 articles Collection Type, assuming you have granted the Public role find permission:
// hooks/use-articles.js
import { useQuery } from '@tanstack/react-query';
const STRAPI_URL = import.meta.env.VITE_STRAPI_URL ?? 'http://localhost:1337';
async function fetchArticles() {
const res = await fetch(`${STRAPI_URL}/api/articles?populate=cover`);
if (!res.ok) throw new Error(`Strapi responded with ${res.status}`);
const { data } = await res.json();
return data; // Strapi 5: data[0].title, data[0].documentId (no .attributes)
}
export function useArticles() {
return useQuery({
queryKey: ['articles', { populate: 'cover' }],
queryFn: fetchArticles,
staleTime: 5 * 60 * 1000,
});
}If you would rather fetch in Server Components and skip the client cache, the guide on React Server Components with Strapi 5 covers that path.
Feature tiers worth knowing before you design the architecture:
- The Content-Type Builder is built in but only available in the development environment. Careful modeling matters because changes become harder as a project grows; the content modeling post helps.
- Role-based access control for admin users is free and on by default. Strapi SSO requires CMS Enterprise or the SSO add-on with Growth, while Audit Logs require Enterprise; Content History and Strapi Releases require Growth or Enterprise.
- Internationalization is built into Strapi 5 (no plugin) but disabled by default. You enable it per Content-Type in the builder, then add locales under Settings.
- The Strapi MCP Server is built in and reached general availability in Strapi 5.49.0. It is free on any plan, opt-in via
server.mcp.enabled, authenticates with Admin tokens, and lets AI clients such as Claude Code and Cursor create, publish, and unpublish content. The MCP GA announcement has setup steps.
Strapi's built-in TypeScript support, including generated types for your Content-Types, is covered in the Vite and TypeScript announcement for Strapi 5. For hosting, Strapi Cloud currently offers Starter ($35/project/month), Pro ($90), and Business ($450) tiers; the free tier was removed, and CMS feature licenses are separate from hosting tiers. The self-hosted comparison lays out the operational trade-offs.
Choosing Your React Stack for Content-Driven Apps
A practical, composable starting point is TanStack Query or Server Components for server state, Zustand for client state, React Hook Form with Zod for forms, and a UI library chosen by design-system fit rather than feature count. TypeScript is the assumed baseline; every library here documents a minimum TypeScript version, from Zustand's 4.5 to TanStack Query's 5.6.
Keep bundle size in the decision, but consider it in context. Google's page experience docs state that "Core Web Vitals are used by our ranking systems," and the current thresholds are LCP at or under 2.5 seconds, INP under 200 ms, and CLS under 0.1. FID stopped being a Core Web Vital on September 9, 2024, so older performance checklists that mention it need updating. The gap between Zustand's 489 B and Redux Toolkit's 13.3 kB shows why you should weigh each dependency's cost across a stack of eight dependencies.
If you are building something content-heavy, a practical starting point is the React and Strapi integration page. From there, you can model your Content-Types and wire one of the data-fetching approaches above before adding UI and animation layers. For a full worked example, the ecommerce tutorial with Next.js and Strapi combines several of these libraries against a live Strapi 5 backend.







