BuildBot

React, Off the Web

Primitives, not divs

Lesson 1 of 5

What you'll learn

  • Map the core RN primitives to the DOM elements you already know
  • Style with StyleSheet.create and understand why there is no CSS cascade
  • Internalize the flexbox differences — column by default, flex on everything

React Native is React — same components, same props, same hooks, same reconciler. What changes is the render target: instead of emitting DOM nodes, your components become real native views (UIView on iOS, android.view.View on Android). That means no div, no span, no img. You compose from a small set of primitives:

| Web | React Native | | --- | --- | | <div> | <View> | | <span>, <p>, <h1> | <Text> | | <img> | <Image> | | <button>, clickable anything | <Pressable> | | a scrolling container | <ScrollView> (or FlatList for long lists) |

import { View, Text, Image, Pressable, StyleSheet } from "react-native";

export default function ProfileCard() {
  return (
    <View style={styles.card}>
      <Image source={{ uri: "https://example.com/ada.png" }} style={styles.avatar} />
      <Text style={styles.name}>Ada Lovelace</Text>
      <Pressable onPress={() => console.log("followed")} style={styles.button}>
        <Text style={styles.buttonLabel}>Follow</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  card: { padding: 16, borderRadius: 12, backgroundColor: "#fff" },
  avatar: { width: 64, height: 64, borderRadius: 32 },
  name: { fontSize: 18, fontWeight: "600" },
  button: { backgroundColor: "#111", padding: 10, borderRadius: 8 },
  buttonLabel: { color: "#fff", textAlign: "center" },
});

Two rules with no web equivalent. First, all text must live inside <Text> — a raw string as a child of <View> throws at runtime. Second, there is no CSS. Styles are plain JS objects (camelCased, unitless numbers meaning density-independent pixels), grouped with StyleSheet.create and attached per component via the style prop.

No cascade, no inheritance

On the web, setting font-family on body styles the whole page. In React Native, styles apply only to the component you put them on. There are no selectors, no specificity wars, no global stylesheets. The one deliberate exception: a <Text> nested inside another <Text> inherits its parent's text styles. To share styles you do what you'd do with any JS value — export objects, or wrap primitives in your own components.

Flexbox, rotated

Every View is a flex container, and the default flexDirection is column, not row — phones are portrait-first. flex: 1 means "fill the available space along the main axis." There is no display: block or inline; layout is flexbox (plus absolute positioning) all the way down.

The column default bites everyone

A row of buttons from the web (display: flex and done) stacks vertically in RN until you add flexDirection: "row" explicitly. When a layout looks transposed, check this first.

The challenge below is a web model of the mapping: build tiny View and Text components over div/span that bake in RN's defaults, then compose a card with them.

Build View and Text (web model)

View renders a div that is a flex container defaulting to column; Text renders a span. Run it, then add flexDirection: 'row' to the tag row's style and watch it un-stack.

Loading editor…
Knowledge check

Why does a horizontal toolbar from the web render as a vertical stack when ported to React Native?

Next: where pages come from without URLs — file-based navigation with expo-router.

Saved on this device. Sign in to sync your progress everywhere.