AniUI Academy

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.

9 min read

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

up to 50
  1. 1.What happens if you put a bare string directly inside a View, with no Text component wrapping it?

  2. 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. 3.What is the difference between require('./logo.png') and { uri: 'https://example.com/logo.png' } as an Image source?

  4. 4.Which best describes what View is analogous to in web development?

4 left to answer