Lesson 5 of 26
The Core Components: View, Text, and Image
How View, Text, and Image work in React Native — the classic gotcha that all text must live inside Text, and how Image sizing differs from the web's img tag.
Three components cover an enormous share of everyday React Native UI:
View for structure, Text for words, and Image for pictures. Each has
a web analogue you already know, and each has at least one rule that isn't
what you'd expect coming from HTML.
View: a container, not a canvas
View is React Native's generic, all-purpose container — the closest
thing to a div. It doesn't render anything visible on its own beyond
whatever styling you give it (background color, border, padding); its job
is to hold and lay out other components.
import { View, StyleSheet } from "react-native";
function Card() {
return (
<View style={styles.card}>
<View style={styles.header} />
<View style={styles.body} />
</View>
);
}
const styles = StyleSheet.create({
card: {
borderRadius: 8,
backgroundColor: "#fff",
overflow: "hidden",
},
header: {
height: 48,
backgroundColor: "#3366ff",
},
body: {
padding: 16,
},
});Nothing about this is exotic if you've built layouts with nested divs —
View composes the same way. The layout model it uses (Flexbox, and only
Flexbox — no CSS Grid) is its own lesson shortly, because RN's Flexbox
defaults differ from the web's in one important way.
Text: the one rule that trips everyone up at first
This is the genuine, stable gotcha in this lesson: all text in React
Native must be inside a Text component. View cannot render text
directly, the way a div can happily contain a bare string. Put text
directly inside a View with no Text wrapper, and it's invalid — React
Native has no way to render it.
import { View, Text } from "react-native";
// Correct — text lives inside Text
function Greeting({ name }) {
return (
<View>
<Text>Hello, {name}!</Text>
</View>
);
}// Invalid — a bare string directly inside View, with no Text
function BrokenGreeting({ name }) {
return (
<View>
Hello, {name}!
</View>
);
}Text also nests inside itself, which is a useful and common pattern for
mixed styling within one paragraph:
function Byline() {
return (
<Text>
Written by <Text style={{ fontWeight: "bold" }}>Anish</Text>
</Text>
);
}The reasoning behind the rule is worth internalizing rather than just
memorizing: View maps to a generic native container view, which has no
built-in concept of rendering a text run — text rendering is its own,
separate native concept (a text label), which is exactly what Text wraps.
It's not an arbitrary restriction; it reflects a genuine difference between
how native platforms model "a box" versus "a run of text" compared to how
a browser's div conflates the two.
Image: sizing works differently than <img>
Image takes a source prop, and that prop takes one of two distinct
shapes depending on where the image comes from:
import { Image } from "react-native";
// A static asset bundled with your app
function Logo() {
return <Image source={require("./assets/logo.png")} style={{ width: 120, height: 40 }} />;
}
// A remote image, loaded at runtime from a URL
function Avatar({ avatarUrl }) {
return (
<Image
source={{ uri: avatarUrl }}
style={{ width: 48, height: 48, borderRadius: 24 }}
/>
);
}require() is for a static asset that ships inside your app bundle — the
bundler resolves it at build time, the same way importing an image file
works in many web bundler setups. { uri: ... } is for anything resolved
at runtime, most commonly a remote URL, but the key behavioral difference
to remember is about sizing: a web <img> can size itself to an image's
natural pixel dimensions once the browser has loaded it, because that
information becomes part of the page's layout process automatically. React
Native generally cannot infer a remote image's intrinsic size the same
way, which is why setting an explicit width and height in style is
the standard, expected pattern for Image — especially for { uri }
sources, where skipping it commonly results in the image not appearing at
all, because it has no size to render at.
Putting the three together
import { View, Text, Image, StyleSheet } from "react-native";
function ProfileCard({ name, bio, avatarUrl }) {
return (
<View style={styles.card}>
<Image source={{ uri: avatarUrl }} style={styles.avatar} />
<View style={styles.info}>
<Text style={styles.name}>{name}</Text>
<Text style={styles.bio}>{bio}</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
card: { flexDirection: "row", padding: 12, alignItems: "center" },
avatar: { width: 56, height: 56, borderRadius: 28, marginRight: 12 },
info: { flex: 1 },
name: { fontSize: 16, fontWeight: "600" },
bio: { fontSize: 13, color: "#666" },
});Every real screen you build in this track from here on will lean on this
same trio: View for structure, Text for words, Image for pictures —
each backed by a real native component, none of it simulated.
What to remember
- View is a generic container, analogous to a div, but renders to a real native view.
- All text must be inside a Text component — a bare string directly inside a View is invalid, unlike on the web.
- Text components can nest inside each other for mixed inline styling within one block of text.
- Image's source prop is either
require('./local.png')for a bundled static asset, or{ uri }for a runtime-resolved (usually remote) image. - Remote images generally need explicit width/height in style, since React Native can't reliably infer their intrinsic size the way a browser can for an img tag.
Check yourself
4 questions · pass 3/4 to unlock Flexbox Layout in React Native
1.What happens if you put a bare string directly inside a View, with no Text component wrapping it?
2.Why does an Image showing a remote picture (via a uri source) usually need explicit width and height set in its style, unlike a web <img> tag?
3.What is the difference between require('./logo.png') and { uri: 'https://example.com/logo.png' } as an Image source?
4.Which best describes what View is analogous to in web development?
4 left to answer