Chapter 1 of 12 ~15 min read

Why React Native & The Mindset Shift

DOM/WebView vs Native Primitives, `

` vs ``, Why Cordova apps felt sluggish vs 60/120fps native rendering, New Architecture overview.


1. The Architectural Mindset Shift: WebView vs Native Widgets

In Apache Cordova, your entire application runs inside a single embedded browser container (an Android WebView). You wrote HTML, CSS, and DOM JavaScript. Every button was an HTML <button> or <div>, and Cordova translated bridge calls into native Java through asynchronous callback strings.

In React Native, there is no browser and no DOM. Your JavaScript executes on a dedicated JavaScript engine (Hermes), while your UI renders into genuine platform-native widgets:

ConceptCordova (Hybrid WebView)React Native (Real Native)
Rendering EngineChromium / Android System WebViewNative Android Views (Fabric Renderer)
UI Primitives<div>, <span>, <p>, <button><View>, <Text>, <Pressable>
StylingCascading CSS stylesheets, classes, web unitsFlexbox in JS via StyleSheet.create(), unitless dp
PerformanceSubject to webview DOM reflow & jank60fps / 120fps fluid native touch response
JS EngineWebView's V8 browser engineOptimized Ahead-of-Time Bytecode (Hermes Engine)

2. Hello World: Cordova vs React Native

Cordova HTML & JS
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="css/index.css">
</head>
<body>
  <div class="app">
    <h1 id="title">Hello Cordova</h1>
    <button id="btn">Click Me</button>
  </div>
  <script src="cordova.js"></script>
  <script>
    document.addEventListener('deviceready', function() {
      document.getElementById('btn').onclick = function() {
        alert('Device Ready!');
      };
    }, false);
  </script>
</body>
</html>
React Native (Expo) Component
// App.tsx
import React, { useState } from 'react';
import { StyleSheet, Text, View, Pressable, Alert } from 'react-native';

export default function App() {
  const [count, setCount] = useState(0);

  const handlePress = () => {
    setCount(prev => prev + 1);
    Alert.alert('React Native', `Button clicked ${count + 1} times`);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello React Native</Text>
      <Pressable style={styles.button} onPress={handlePress}>
        <Text style={styles.buttonText}>Click Me ({count})</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fff' },
  title: { fontSize: 24, fontWeight: 'bold', marginBottom: 16 },
  button: { backgroundColor: '#087ea4', paddingHorizontal: 20, paddingVertical: 12, borderRadius: 8 },
  buttonText: { color: '#fff', fontWeight: '600' }
});
Key Takeaway: No `deviceready` event required!

In Cordova you had to delay all JavaScript execution until the bridge sent deviceready. In React Native, native modules are wired directly during initialization with Hermes and TurboModules. You can call native functions immediately inside standard React lifecycles and hooks!