I finally ripped native-base out of our production app last night. We’ve been maintaining this massive 150-screen monster since 2021, and the technical debt was starting to physically hurt.
If you’ve been working in React Native for the past few years, you already know the story. NativeBase v3 was incredibly popular when it dropped. It gave us a beautiful utility-first API. But as our app grew, the performance issues became impossible to ignore. The React context re-renders were brutal on low-end Android devices. The creators knew it too, which is exactly why they built gluestack-ui to replace it.
But management is never going to approve a three-month UI rewrite just because developers are complaining about frame drops. We needed a bridge.
Testing the Migration Adapter
Enter the @gluestack-ui/themed-native-base migration library. I’ve been watching this thing move through its alpha and beta phases, and I finally decided to be the guinea pig for our staging environment.
Well, that’s not entirely accurate — I’ll be honest. I expected a complete disaster. Drop-in replacements for complex UI frameworks usually are. You swap a dependency, and suddenly half your buttons are rendering off-screen.
I ran this on my M2 MacBook Pro running Sonoma 14.2, against a codebase stuck on React Native 0.73.4 and NativeBase 3.4.28. The actual mechanical swap is pretty clever. You don’t go through and change thousands of import statements. Instead, you hijack the imports at the bundler level.
You just drop this into your Babel config:
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
[
'module-resolver',
{
alias: {
'native-base': '@gluestack-ui/themed-native-base',
},
},
],
],
};
};
The initial reload was weirdly quiet. Most of our basic layout components—the Box, VStack, and HStack instances we had plastered everywhere—just worked. No red screens. No exploded layouts. The visual regression tests actually passed for about 80% of our screens on the first try.
The Hook Nightmare
Then I hit the custom hooks. This is where the adapter stops holding your hand.
But generally, if your app heavily relies on useTheme or useToken to pull specific design tokens into non-UI components (like passing theme colors to a third-party charting library), you are going to spend some time refactoring.
The adapter does a great job translating the JSX props, but the underlying theme object structure in gluestack is fundamentally different. NativeBase nested things in a way that gluestack flattens out.
Here is a specific gotcha that burned two hours of my life. If you had custom font weights mapped in your old NativeBase theme config, the adapter occasionally resolves them as undefined if you try to pull them via hooks without explicit string casting. All my bold text suddenly looked like regular weight on Android, but only inside components where I was manually passing the style prop instead of using the utility props.
I had to rewrite several of our custom wrappers to stop relying on the old hook patterns and instead use the new gluestack token resolver:
// The old way that broke silently
import { useToken } from 'native-base';
const MyChart = () => {
const [primaryColor] = useToken('colors', ['primary.500']);
return <LineChart color={primaryColor} />;
}
// The fix using the adapter's expected format
import { useToken } from '@gluestack-ui/themed-native-base';
const MyChart = () => {
// You have to be much more explicit with the token paths now
const primaryColor = useToken('colors', 'primary500');
return <LineChart color={primaryColor} />;
}
Real Performance Numbers
I didn’t just do this to use newer syntax. I wanted my frames back.
And I profiled the app before and after the swap using React Native Debugger. Our old NativeBase setup was causing massive render delays on a heavily nested feed view. We were seeing 45-50ms render times per item when scrolling fast.
After swapping to the themed gluestack adapter, that dropped to about 18ms. We also cut our initial JS bundle size by roughly 14%.
Is it the pure, unadulterated performance of raw gluestack-ui v2? Probably not. You’re still carrying some adapter overhead. If you want absolute bare-metal performance, you should be looking at Tamagui or building your own components with Nativewind. But for a find-and-replace migration that I finished over a weekend? I’ll take that performance bump every single time.
What Happens Next
Look, don’t treat this adapter as your forever home. It’s a temporary bridge to get you off a deprecated library without halting your product roadmap.
My plan is pretty straightforward. I’m using this adapter to stop the bleeding today. It gets us onto a maintained dependency tree and fixes the worst of our performance bottlenecks. But by Q1 2027, my goal is to incrementally replace the aliased imports with pure gluestack-ui components, one feature branch at a time.
And if you’ve been dreading this migration and putting it off, just do it. The tooling is finally stable enough to handle complex production apps. Just keep a close eye on your typography tokens and be ready to rewrite a few custom hooks. It beats rewriting the whole app.












Leave a Reply