Why React Native & The Mindset Shift
DOM/WebView vs Native Primitives, `
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:
| Concept | Cordova (Hybrid WebView) | React Native (Real Native) |
|---|---|---|
| Rendering Engine | Chromium / Android System WebView | Native Android Views (Fabric Renderer) |
| UI Primitives | <div>, <span>, <p>, <button> | <View>, <Text>, <Pressable> |
| Styling | Cascading CSS stylesheets, classes, web units | Flexbox in JS via StyleSheet.create(), unitless dp |
| Performance | Subject to webview DOM reflow & jank | 60fps / 120fps fluid native touch response |
| JS Engine | WebView's V8 browser engine | Optimized Ahead-of-Time Bytecode (Hermes Engine) |
2. Hello World: Cordova vs React Native
<!-- 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>
// 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' }
});
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!