Profile    Mohammed Shiroz Status   Loading  
Logo
Share This
Back to blog
Filter by:
Tags
//Article title

React Native for Web Developers: What Changes When There's No Browser

About Post

You know React. You've shipped components, hooks, forms, the lot. So React Native should be a weekend of reading, right?

Then you write <div> out of habit and the app crashes. You put some text straight inside a View and get a red screen. Your flex layout stacks everything vertically for no reason you can see.

React Native is React. The component model, state, props and hooks all carry over. What changes is everything underneath: there's no browser, no DOM and no CSS. Here's the map I wish someone had handed me when I moved from web to mobile.

The big shift: you're not rendering HTML

On the web, React builds a tree of DOM nodes and the browser draws them. In React Native, your components describe real native views: a View becomes a native view on iOS and Android, a Text becomes a native text element. Your JavaScript runs in its own engine (Hermes by default) and talks to the native side.

That one fact explains most of the surprises:

  • There's no document, no window.localStorage, no querySelector.
  • Browser APIs you took for granted are either missing or replaced by a library.
  • Anything the phone does natively (camera, push notifications, biometrics) needs a native module behind it.

A quick translation table

On the webIn React Native
<div><View>
<p>, <span><Text> (all text must live inside one)
<img><Image> (needs an explicit size for remote images)
<button>, onClick<Pressable>, onPress
<input><TextInput>
A long list with .map()<FlatList> (renders only what's on screen)
Page scrolls by defaultNothing scrolls unless you use ScrollView or a list
localStorageAsyncStorage, or SecureStore for tokens

The last two rows catch everyone. A screen that's taller than the phone simply gets cut off until you wrap it in a ScrollView. And a login token does not belong in plain AsyncStorage; use the platform's secure storage (Expo's SecureStore wraps Keychain on iOS and Keystore on Android).

Styles: it looks like CSS, but it isn't

Styling uses JavaScript objects with camelCase names, usually created with StyleSheet.create:

import { StyleSheet, Text, View } from 'react-native';

export function RentCard({ amount }) {
  return (
    <View style={styles.card}>
      <Text style={styles.label}>Next rent due</Text>
      <Text style={styles.amount}>{amount}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  card: { padding: 16, borderRadius: 12, backgroundColor: '#fff' },
  label: { fontSize: 14, color: '#666' },
  amount: { fontSize: 24, fontWeight: '600' },
});

The differences that trip web developers up:

  • Flexbox is the only layout system, and flexDirection defaults to column, not row. That's why everything stacks.
  • No cascade, very little inheritance. A style on a View does not flow down to the text inside it. Text styles only inherit from a parent Text.
  • Numbers, not pixels. padding: 16 means 16 density-independent points, so it looks roughly the same on every screen. No rem, no media queries; use useWindowDimensions when you need to adapt to screen size.
  • No hover. Fingers don't hover. Pressed states come from Pressable.

If you miss utility classes, libraries like NativeWind bring Tailwind-style class names to React Native. Under the hood they still compile down to these style objects.

Navigation is a stack, not a URL bar

On the web, the browser owns history and the back button. On mobile, your app owns them. Navigation libraries keep a stack of screens: pushing a screen slides it in, going back pops it off, and the previous screen is still alive underneath with its state intact.

That last part matters. A screen you navigated away from hasn't unmounted, so a useEffect that fetches data on mount won't run again when the user comes back. Refreshing on focus is a separate hook (useFocusEffect in React Navigation).

The two common choices are React Navigation and Expo Router. Expo Router gives you file-based routing that will feel familiar if you've used Next.js, built on top of React Navigation.

Native modules, and why Expo matters

Pure JavaScript only gets you so far. Taking a photo, receiving a push notification or reading a fingerprint needs native code in Swift, Kotlin or Java. Libraries ship that native code as native modules, and your JavaScript calls them.

This used to be the painful part: installing a library meant editing Xcode and Gradle files by hand. Expo changed that for most teams. It gives you a large set of maintained modules (camera, notifications, secure storage, file system and more), and config plugins that make the native changes for you at build time. When you need a module Expo Go doesn't include, you make a development build, which is your own version of Expo Go with your native code inside.

The tenant app I worked on for Kate PMS is built with React Native and Expo, and that setup is a big reason a web-heavy team can ship a mobile app without becoming full-time iOS and Android specialists.

Two platforms, two personalities

"Write once, run everywhere" is mostly true. The remaining part is where the bugs live:

  • Shadows use different properties: shadow* on iOS, elevation on Android.
  • The keyboard behaves differently, so KeyboardAvoidingView usually needs a different behavior per platform.
  • Notches, status bars and gesture bars need safe-area handling.
  • Permissions are requested differently, and users can deny them.

Platform.OS and Platform.select handle the small differences. For bigger ones, files named Button.ios.js and Button.android.js are picked automatically. And test on a real, mid-range Android phone, not just the simulator on your fast laptop.

Performance basics that actually matter

Most React Native slowness comes from a small set of habits:

  • Rendering long lists with ScrollView and .map(). It renders every item at once. Use FlatList (or a faster list library) with a stable keyExtractor.
  • Heavy work on the JavaScript thread. Taps and animations wait while your JS is busy. Keep big computations out of render, and use the native driver or Reanimated for animations.
  • Unnecessary re-renders. The same React rules apply, but you feel them more on a cheap phone.
  • Oversized images. Don't download a 4000-pixel photo to show a thumbnail.
  • Testing in debug mode. Development builds are slower. Judge performance on a release build.

The mental model: React Native keeps React and replaces the browser. Your component skills transfer on day one. Your assumptions about HTML, CSS, URLs and browser APIs don't, so question every one of them.

Where to start

If you're a web developer trying React Native this month, my advice: start with Expo, use Expo Router, put tokens in SecureStore, reach for FlatList early, and keep a real Android phone on your desk. The first week feels strange. By the second, you'll be surprised how much of your React knowledge just works.

If you've made the move from web to mobile, what was the habit that took you longest to unlearn?

Comments (0)
Leave your review

Thanks for your valuable comments. Your comments has been updated and appreciate your getting in touch...

01. About Shiroz

Mohammed Shiroz

Hi, I'm Mohammed Shiroz, a software engineer and AI enthusiast from Sri Lanka who turns ideas into intelligent, real-world solutions. With over 9 years of hands-on experience, I currently lead real estate ERP development at Kate Group, a...

03.My Projects

04. Categories

Ready To order Your Project ?

Get in Touch
Close