The Hype vs The Reality
React 19 shipped in late 2024 with the biggest set of new features since hooks. Actions, useOptimistic, useActionState, use(), the React Compiler, and improved ref handling. Six months of running it in production across three projects, and we have opinions. Here is the honest breakdown. Actions Are the Real Deal Actions are the single best feature in React 19 and the one that actually changes how you write code day to day. The pattern is simple — instead of manually managing loading states, error states, and form submissions with useState and event handlers, you pass an async function to a form's action prop. React handles the pending state, error boundaries, and optimistic updates automatically. In practice, this eliminated about 30% of the boilerplate in our form-heavy applications. No more isLoading useState. No more try-catch-finally blocks in every submit handler. No more manually resetting form state after submission. You just write the async function that does the work and React handles the ceremony. useOptimistic Is Great but Niche useOptimistic lets you show an optimistic UI update immediately while the server request is in flight, then reconcile when the response comes back. Think of a like button that increments instantly instead of waiting for the API call. The API is clean and it works well. But we found ourselves using it in maybe 10% of our components. Most interactions in business applications do not benefit from optimistic updates — you want to show the user that something is loading, not pretend it already happened. For social features, real-time collaboration, and highly interactive UIs, useOptimistic is excellent. For forms, settings pages, and admin panels, the standard Actions pattern is better. The React Compiler Is Impressive but Cautious The React Compiler — formerly React Forget — automatically memoises your components and hooks. No more useMemo, useCallback, and React.memo decisions. The compiler analyses your code and inserts memoisation where it determines it will help. We enabled it on one project and the results were genuinely good. Re-renders dropped noticeably in our more complex component trees. Performance metrics improved without changing any application code. But we hit edge cases. Components that relied on referential equality for non-React purposes broke subtly. A few third-party libraries that did unusual things with refs produced warnings. The compiler is conservative by design — it would rather skip optimisation than break behaviour — but the edge cases made us cautious about enabling it on our larger projects without thorough testing. use() Simplifies Data Loading The use() hook lets you read a promise or context in render, which simplifies data loading patterns significantly. Combined with Suspense boundaries, you can write data-fetching components that look synchronous. No more loading state management, no more conditional rendering based on whether data has arrived. The mental model is cleaner. But it requires you to commit fully to the Suspense architecture, and many existing codebases have deeply embedded loading patterns that are not trivial to migrate. Ref Handling Improvements Refs can now be passed as regular props instead of requiring forwardRef. This sounds minor but it eliminated one of the most annoying patterns in React. No more forwardRef wrapper components, no more explaining to junior developers why some components need forwardRef and others do not. Clean up callbacks on refs also work now, which fixes a long-standing issue with ref lifecycle management. Small improvement, big quality of life upgrade. The Migration Reality Upgrading from React 18 to 19 was smoother than we expected. The breaking changes are minimal — mostly around removing deprecated APIs like defaultProps on function components and string refs that should have been updated years ago. Our largest project migrated in about four hours, most of which was updating third-party dependencies. If your codebase is reasonably modern and you were not using deprecated patterns, the upgrade is straightforward. The Verdict React 19 is a good release. Not a revolutionary one — you are not going to rewrite your architecture around it. But Actions genuinely improve the form and mutation story, the compiler is promising for performance, and the quality-of-life improvements like ref cleanup and use() make daily development noticeably smoother. Was it worth the upgrade? Yes, but not urgently. If you are starting a new project, use React 19 from day one. If you have an existing React 18 project, upgrade when you have a natural window — a sprint break, a major feature milestone — rather than rushing it. The features are good. The migration is manageable. The ecosystem has caught up. There is no reason to stay on 18 anymore, but there is also no emergency.