AniUI Academy

React 19 in React Native

Modern React runs on React Native too — the Compiler, the use hook, Actions, Suspense, Fragment refs — with the same meaning, plus one honest caveat about View Transitions.

10 min read

The React course covered modern React top-to-bottom: the Compiler, Actions and useFormStatus, use(), stable Suspense semantics, Fragment refs, Trusted Types, View Transitions. One honest question to ask before spending time learning any of that is: does it come with me when I ship to a phone, or is it web-only?

The short answer: almost all of it comes with you. One lesson's worth of API — View Transitions — is a web-specific exception. This lesson walks the line.

Current React Native runs modern React

React Native is a React renderer: it takes the same React you'd use in a browser and plugs in a different "turn this tree into actual UI" backend — Fabric for native views instead of react-dom for the DOM. Because the React half is the same library, the same version numbers apply, and the same new features are available at the same time.

Hermes, React Native's default JavaScript engine, has been keeping pace with the language features modern React depends on — the syntax for Actions and async components, the specific semantics of queueMicrotask and iterators that use() relies on — so there is no "we have modern React, but the engine doesn't support the APIs" gap worth planning around.

The practical consequence is that the React course lessons on the Compiler, use(), Actions, useFormStatus, Suspense, Fragment refs, and the Rules of React all apply directly. Your existing mental model carries over without translation.

The Compiler on native

The React Compiler is a Babel plugin that rewrites your components at build time to insert the memoisation you'd otherwise write by hand with useMemo, useCallback, and React.memo. React Native projects compile their JS through Babel before Metro bundles it, so the Compiler slots in exactly the same way as on the web.

What that means in a native project:

  • The setup is the same: add the Compiler's Babel plugin to the project's Babel config, make sure your code follows the Rules of React (no mutating props or state during render, no reading from refs during render, etc.), and measure.
  • The win is the same: fewer unnecessary re-renders of child components, without you having to remember to wrap every callback.
  • The failure mode is the same: components that break the Rules can behave incorrectly after the Compiler's transformation, which is why the Compiler ships with a linter that flags the patterns most likely to bite.

The relevant React course lesson on the Compiler is the one to re-read when turning this on in a native project. The guidance doesn't change because the renderer underneath is Fabric.

use, Actions, and Suspense

The use() hook unwraps a Promise or Context during render, suspending the component while waiting. The suspending behaviour is a React concept, not a renderer-specific one, so use() works the same way against a native renderer: during the suspend, the nearest Suspense boundary shows its fallback; when the promise resolves, the subtree resumes rendering.

The same is true for Actions and the form hooks (useFormStatus, useOptimistic, useActionState). React Native doesn't have a <form> element the way the DOM does, but the hooks themselves are not married to the HTML form element — they're wrappers over a pending-state and optimistic-state model that you can wire to any UI, and the common pattern on native is to call the action imperatively from a Pressable's onPress while reading useFormStatus from a wrapper component. Everything the React course taught about when an Action is pending and how optimistic updates roll back on error applies here unchanged.

Stable Suspense for data fetching is the same story: a native component tree can suspend, show a fallback, and resume, and nothing about the Fabric renderer changes that contract.

Fragment refs on native

Fragment refs — attaching a ref to a <Fragment> and getting back a handle that applies an operation to every child — were introduced in the React course as a way to drop the useless wrapper <div> you used to need around a group of siblings so you could observe them with an IntersectionObserver.

The native version of the same problem exists: a list of sibling <View>s inside a flex or grid parent, where introducing a wrapper <View> throws off the layout. Fragment refs solve it the same way — the handle exposes operations across the child set — but the actual helpers available are the ones that make sense for a native tree: focus/scroll iteration and layout measurement in native-renderer terms, rather than browser Observer APIs that don't exist in Fabric.

The shape of the API is the same. The specific methods the handle exposes differ, because the underlying rendering target is different.

The honest exception: View Transitions

The React course covered <ViewTransition>, React's declarative wrapper over the browser's View Transitions API. That API is a browser feature: the browser takes a snapshot of the current DOM, lets React commit the new one, and animates between the two using ::view-transition-* pseudo-elements and CSS.

A native renderer has no equivalent of any part of that. Fabric doesn't take CSS-animated snapshots of a view hierarchy; iOS and Android compose their own view trees with their own animation systems. So the exact <ViewTransition> component doesn't ship for native: it would have nothing to call into.

The idea — declaratively animating between two UI states — is reachable on React Native through tools that already exist and that most RN developers already use:

  • Animated and LayoutAnimation from React Native core.
  • react-native-reanimated for more expressive, native-thread animations.
  • Shared-element transition libraries built on top of those.

If you learned the mental model from the View Transitions lesson — "I want the before and after states of this UI to be connected by an animation, not just swapped" — that model is the one to carry over. Which tool implements it differs by platform. Treat <ViewTransition> itself as a web-only API for now, not a cross-platform one.

What to remember

  • React Native runs on modern React, not a legacy fork. The Compiler, use(), Actions, useFormStatus, stable Suspense, and Fragment refs are available with the same semantics the React course described.
  • Hermes supports the language features those APIs need, so there is no "React has the feature but the engine doesn't" gap to work around.
  • The React Compiler is a Babel plugin; it slots into a React Native project the same way it slots into a web React project. Same setup, same Rules of React, same measurement discipline.
  • use(), Actions, and Suspense are renderer-agnostic — their contracts don't depend on whether the underlying renderer is react-dom or Fabric.
  • Fragment refs apply on native, but the handle's specific helpers are native-renderer flavoured — not browser Observer APIs that have no native equivalent.
  • <ViewTransition> is the honest exception: it depends on a browser API with no native counterpart. The concept maps onto native through existing animation libraries, but the component itself doesn't ship there.

Check yourself

4 questions · pass 3/4 to unlock Debugging Tools for React Native

up to 50
  1. 1.What is the relationship between the React version your React Native app runs and the one you learned in the React course?

  2. 2.Can you turn on the React Compiler in a React Native project?

  3. 3.Which of these React 19 APIs is a straight port that behaves the same in React Native as in React on the web?

  4. 4.React 19 adds the <ViewTransition> component for animating UI state changes in the DOM renderer. What's the honest state of that on native?

4 left to answer

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.