React Native Tooling in 2026: What I Actually Use on Real Projects

In 2026 I build React Native apps with Expo and development builds, not Expo Go. Hermes handles the JS engine by default, and I only skip Expo for brownfield work inside an existing native app. That combo gives fast iteration plus real native access.
Part of the complete app development guide.
On this page
- Start with Expo, and stop apologizing for it
- Hermes is the default, and that matters
- Check your engine, don’t assume
- Navigation: expo-router or React Navigation
- Animation: Reanimated, and only Reanimated
- The New Architecture is no longer optional
- Storage: MMKV over AsyncStorage
- EAS Build and Submit for the boring parts
- Testing: keep it light
- What I’d skip in 2026
- The actual short list
- FAQ
- Do I still need to eject from Expo in 2026?
- Is React Native fast enough for a production app?
- What’s the biggest mistake you see in React Native projects?
Most “best React Native tools” lists are written by people who have never shipped an app that broke on a Tuesday because a native module didn’t compile for iOS 19. I have. I build web and mobile software from Commack, and this is the stack I actually reach for in 2026, with the tradeoffs spelled out.
Start with Expo, and stop apologizing for it
The old advice was “Expo is fine for prototypes, eject for real apps.” That advice is dead. Expo’s development builds and config plugins mean you can write custom native code and still keep the managed workflow. If you’re starting a React Native app today and you’re not using Expo, you’re volunteering for a week of Xcode and Gradle pain you don’t need to endure.
The one real reason to skip Expo is if you’re dropping into an existing native app (a brownfield integration). Otherwise, use it.
npx create-expo-app@latest my-app
cd my-app
npx expo install expo-dev-client
# then build a dev client instead of using Expo Go
npx expo run:ios
npx expo run:android
Note the shift: expo run:ios builds a real native app locally. You get fast iteration and full native access. Expo Go is now only for quick demos.
Hermes is the default, and that matters
Hermes has been the default JS engine for a while now, and in 2026 it’s just how React Native runs. The practical upside is startup time and memory. The practical downside is that some debugger workflows and older libraries that assumed JSC behave differently. If a library claims to be “React Native compatible” but hasn’t been touched since 2022, test it before you build a feature on top of it.
Check your engine, don’t assume
import { HermesInternal } from 'react-native';
if (HermesInternal) {
console.log('Running on Hermes');
} else {
console.log('Not Hermes (unusual in 2026)');
}
Navigation: expo-router or React Navigation
expo-router gives you file-based routing, deep links, and typed routes without wiring anything up. If you’re on Expo, use it. If you’re not on Expo, React Navigation is still the right answer and always has been.
The mistake I see most: people install expo-router, then also install React Navigation and use both. Pick one. expo-router is built on React Navigation under the hood, so you get the same primitives with less config.
// app/(tabs)/index.tsx
import { View, Text } from 'react-native';
import { Link } from 'expo-router';
export default function Home() {
return (
<View>
<Text>Home</Text>
<Link href="/settings">Go to settings</Link>
</View>
);
}
Animation: Reanimated, and only Reanimated
If you’re animating anything that needs to feel smooth on a mid-range Android phone, use Reanimated. It runs your animation logic on the UI thread, which is the difference between 60fps and a slideshow. The Animated API that ships with React Native still works, but it’s a legacy path at this point.
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
export function BouncyBox() {
const scale = useSharedValue(1);
const style = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
return (
<Animated.View
style={[{ width: 100, height: 100, backgroundColor: '#2b6cb0' }, style]}
onTouchStart={() => {
scale.value = withSpring(1.4);
}}
onTouchEnd={() => {
scale.value = withSpring(1);
}}
/>
);
}
Reanimated 4 requires the New Architecture, which brings me to the next point.
The New Architecture is no longer optional
By 2026 the New Architecture (Fabric renderer, TurboModules, JSI) is the default and the old bridge is on its way out. Most of the ecosystem has caught up. What this means for you practically:
- Native modules need to be TurboModule-compatible. Most popular ones are. Check the repo’s last commit date.
- You should be on React Native 0.80 or newer. Older versions will fight you.
- If a dependency hasn’t shipped a release in two years, assume it’s broken until proven otherwise.
This is also where a lot of teams get stuck. If you’re migrating an app that’s been in production for years, that’s less a tooling question and more a custom software engineering project with a real migration plan behind it.
Storage: MMKV over AsyncStorage
AsyncStorage is async and slow-ish. MMKV is synchronous, memory-mapped, and it just works. For anything you read on app start (auth tokens, user prefs, feature flags), MMKV is the better call.
import { MMKV } from 'react-native-mmkv';
export const storage = new MMKV();
storage.set('token', 'abc123');
const token = storage.getString('token'); // synchronous
// Zustand persist, if you use Zustand
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
export const useStore = create(
persist(
(set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })) }),
{
name: 'app-store',
storage: createJSONStorage(() => ({
setItem: (k, v) => storage.set(k, v),
getItem: (k) => storage.getString(k) ?? null,
removeItem: (k) => storage.delete(k),
})),
}
)
);
EAS Build and Submit for the boring parts
Signing certificates, provisioning profiles, and App Store Connect uploads are the least interesting part of mobile development. EAS handles all of it. You write a config file, run one command, and get a build artifact.
{
"build": {
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}
eas build --platform ios --profile production
eas submit --platform ios
For a solo dev or a small team, this replaces a genuinely painful CI setup. For larger teams, you can still run EAS locally on your own runners if you have compliance constraints.
Testing: keep it light
Full end-to-end suites for React Native are expensive to maintain and they break constantly. What actually pays off:
- Jest for pure logic (formatters, reducers, API response parsing).
- React Native Testing Library for component behavior, not snapshots.
- Maestro for a handful of critical user flows (login, checkout, onboarding).
Skip snapshot tests. They pass when nothing changed and fail when you fix a typo, which trains everyone to ignore them.
What I’d skip in 2026
- Detox. Great in theory, brutal in CI. Maestro covers 90% of what most teams need with a fraction of the setup.
- Redux for new apps. Zustand or Jotai gets you there with less ceremony. Redux Toolkit is fine if you already have it.
- Any UI kit that hasn’t shipped since 2023. The New Architecture broke a lot of them.
- Custom native code unless you genuinely need it. Config plugins cover most cases now.
The actual short list
If you want the one-screen version: Expo, expo-router, Reanimated, MMKV, Zustand, EAS, Jest plus Testing Library, Maestro. That’s it. Everything else is a judgment call based on what you’re building.
The tooling isn’t the hard part anymore. The hard part is knowing which library will still be maintained in eighteen months, and that’s a judgment you build by shipping things and watching what breaks.
FAQ
Do I still need to eject from Expo in 2026?
No. Development builds and config plugins let you add custom native code while staying in the managed workflow. Ejecting is a last resort, not a rite of passage.
Is React Native fast enough for a production app?
Yes, if you use Reanimated for animations and keep heavy work off the JS thread. The apps that feel slow are usually fighting the old Animated API or doing synchronous work in render.
What’s the biggest mistake you see in React Native projects?
Stacking libraries that do the same job. Two navigation libraries, two state managers, two storage layers. Every one of those adds a failure mode and a reason the next upgrade takes three weeks instead of three hours.


