EngineeringWriting

React to React Native: A Mental Model Shift

The mindset shift that matters more than APIs when you move from web habits to native constraints.

Nov 10, 2025
5 min read
Aadarsh Srivastava
How performance thinking made me unlearn the browser

I used to think performance was about using the right layer

Before React Native entered the picture, I already cared a lot about performance, but very much from a web developer's point of view.
My mental model was simple: if something could be done in HTML, do it there. If it was about presentation, let CSS handle it. Bring in JavaScript only when the platform genuinely needed help. Not because JavaScript is bad, but because it's expensive compared to the other two.
Over time this got easier as the web caught up. <dialog> cut out a lot of custom modal logic. Popover APIs made common patterns simpler. Semantic HTML stopped being just an accessibility concern and became a way of letting the browser do work it already knows how to do well.
At some point I realized I wasn't optimizing React. I was optimizing how much work I was asking the browser to do.

Performance makes you aware of the browser

In my previous role, performance wasn't optional. Organic traffic was a major acquisition channel, so Core Web Vitals weren't abstract numbers, they moved the business. When INP was introduced as a Core Web Vital, the focus shifted from how fast the page loads to how fast it reacts.
There wasn't a playbook for that, so we profiled a lot: long tasks, layout recalculations, event handlers that looked innocent but blocked interactions longer than expected. The more time I spent in the Performance tab, the clearer one thing became: the browser wasn't slow, it was busy, and usually we were the ones who'd made it that way.
Performance work stopped being about tricks and started being about restraint: fewer renders, clearer layout intent, less unnecessary coordination between parts of the UI. At the time I thought this was just what good web performance work looked like. Then I started working with React Native.

When the browser disappears

In January 2025, after joining my current team, I was asked if I could work with React Native. I hadn't before, but I said yes.
At first it felt familiar: hooks, components, state, all the same shapes. Then something felt off. Not missing features. Missing assumptions. The biggest shift wasn't learning new APIs, it was realizing how much I'd been quietly relying on the browser without noticing. In React Native, that layer just isn't there. No DOM, no CSS cascade, no layout engine smoothing over ambiguity behind the scenes. React isn't running inside an environment anymore. React is the environment.

Same React, different constraints

React Native gets described as "React for mobile," which is technically true and also a little misleading. What actually changes is the constraint surface.
React Native is React in a layout-first, resource-constrained environment where every bit of work is more visible and more costly. If it feels unintuitive at first, it's rarely because the concepts are unfamiliar. It's because habits formed in a forgiving runtime don't carry over cleanly. Once I stopped expecting the platform to smooth things over for me, it started making a lot more sense.

Where web intuition starts to strain

The web is powerful because it absorbs an enormous amount of complexity on your behalf: layout, reflow, painting, accessibility, event handling, decades of it. That's a real feature. It also means an inefficient structure can survive far longer than it should.
React Native doesn't give you that buffer. Every View maps to native UI. Every layout pass matters. Every render shows up somewhere you can see it. That directness is uncomfortable at first and clarifying once you adjust to it.

From screens to layout primitives

The most useful shift I made was to stop thinking in screens and start thinking in layout primitives. Instead of asking how something should look on a given device, I started asking whether it's fundamentally a row or a column, where the spacing actually comes from, what's constraining the size, and which alignment rule is doing the work. Answer those clearly and the UI tends to scale on its own, without device-specific special cases.

Sharing logic without forcing UI

Another thing React Native makes obvious is where cross-platform sharing stops paying off. Domain logic, state, and behavior travel well across platforms. Rendering abstractions usually don't. Hooks travel; views don't always need to. Duplicating UI code can feel wrong at first, but it's often the more honest choice, especially when the underlying platforms genuinely behave differently.

Performance stops being a cleanup step

On the web it's common to treat performance as something you revisit later. React Native doesn't really allow that. View depth, render frequency, layout clarity: small decisions here show up fast, and the feedback loop is too tight to ignore. Over time that constraint is useful. It forces you to be intentional up front instead of reactive after the fact.

The thread that connects it all

Looking back, the through-line is clear enough. The same instincts that led me to prefer native browser features over custom JavaScript, clear structure over clever abstraction, and less work over deferred work, are exactly what React Native demands by default.
Make the runtime's job simpler and the system gets more predictable. Different platform, same lesson. Once that clicked, React Native stopped feeling foreign, and React on the web started feeling sharper.