Build screens with View, Text, Pressable and StyleSheet instead of HTML and CSS.
Why it matters
You already know React for the web, where JSX becomes HTML: <div>, <p>, <button>. React Native uses exactly the same JSX syntax, components, props and hooks, but there is no HTML and no CSS on a phone. Your JSX must use React Native's components, and styles are JavaScript objects. Knowing the mapping saves you an afternoon of "why is nothing rendering?".
The core components
| Web habit | React Native | Notes |
|---|---|---|
<div>, <section> | <View> | A box for layout. It cannot hold raw text. |
<p>, <span>, <h1> | <Text> | All text must be inside <Text>. |
<img> | <Image> | Needs a source and usually a width and height. |
<button>, clickable <div> | <Pressable> (or <Button>) | onPress, not onClick. |
<input> | <TextInput> | onChangeText gives you the string directly. |
| page scrolling | <ScrollView> or <FlatList> | Views do not scroll by themselves. |
The most common error for web developers is putting text straight into a View:
// Crashes with "Text strings must be rendered within a <Text> component"
<View>Hello</View>
// Correct
<View>
<Text>Hello</Text>
</View>
Styling with StyleSheet
Styles are plain objects with camelCase property names, and numbers are density-independent pixels (no px):
import { StyleSheet, View, Text, Pressable } from "react-native";
export default function Card({ title, done, onToggle }) {
return (
<View style={styles.card}>
<Text style={[styles.title, done && styles.done]}>{title}</Text>
<Pressable onPress={onToggle} style={styles.button}>
<Text style={styles.buttonText}>{done ? "Undo" : "Done"}</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
card: { padding: 16, borderRadius: 12, backgroundColor: "#fff", flexDirection: "row", alignItems: "center" },
title: { flex: 1, fontSize: 18 },
done: { textDecorationLine: "line-through", color: "#666" },
button: { paddingVertical: 8, paddingHorizontal: 12, borderRadius: 8, backgroundColor: "#2563eb" },
buttonText: { color: "#fff", fontWeight: "600" },
});
Three things to notice:
- Style arrays.
style={[styles.title, done && styles.done]}combines styles. Later entries win, and falsy entries (false,null,undefined) are ignored. That is how you apply conditional styles without string class names. - Flexbox by default. Every
Viewis a flex container, and the defaultflexDirectioniscolumn(on the web it isrow).flex: 1makes a child fill the remaining space. - No cascade. Styles do not inherit from parents, except that nested
<Text>inherits text styles from an outer<Text>. You cannot set a font on aViewand expect the text inside to use it.
StyleSheet.create mostly helps by keeping styles in one place and validating property names in development. React Native also exports StyleSheet.flatten, which merges a style array into one object; it is handy for tests and for reading the final value of a style.
Worked example: merging styles by hand
To understand how style arrays work, imagine writing the merge yourself. Given [base, isActive && active, { opacity: 0.5 }], you walk the array left to right, skip falsy entries, flatten nested arrays and copy each object's properties over the result:
function merge(style) {
if (!style) return {};
if (Array.isArray(style)) {
return style.reduce((acc, s) => Object.assign(acc, merge(s)), {});
}
return { ...style };
}
That small function is the whole idea behind StyleSheet.flatten. You will write your own version in the Do tab.
Common mistakes
- Raw text in a
View, or a string with a stray space between components. Wrap it in<Text>. - Units in strings:
padding: "16px"is invalid. Use numbers (16) or percentages as strings ("50%"). - Expecting
onClick. UseonPressonPressable. - Expecting the page to scroll. Wrap long content in
ScrollView, and useFlatListfor long lists. - Expecting CSS inheritance. Set text styles on the
Textitself (or a parentText).
Quick recap
- Use
Viewfor boxes,Textfor every piece of text,Pressablefor touches,TextInputfor typing andImagefor pictures. - Styles are objects; combine them with arrays where later entries win and falsy ones are ignored.
- Layout is Flexbox with
columnas the default direction.
Try it
In the Do tab you will write two helpers: one that maps an HTML tag to the React Native component you would use, and one that flattens a style array exactly like StyleSheet.flatten. The exercise is plain JavaScript (no JSX), so it runs in your browser.