0% completed
Using Self-Closing Tags in JSX
On This Page
Why JSX Requires the Slash
Why Developers Prefer the Short Form
Finishing the Profile Card
<Image></Image> and <Image /> compile to the same call and produce the same element. In our test, the two versions gave equal props and an identical rendered tree. The second form is a self-closing tag, which is a shorter way to write a tag with nothing between its opening and closing parts.
The slash at the end of the tag tells the JSX parser that no closing tag follows. You can use this form on any component, built-in or your own, whenever it has no children. This includes View and Text, because the choice depends on how you use a tag rather than on which component it is.
Why JSX Requires the Slash
HTML has elements such as img that never have a closing tag, and you can write <img> with no slash. JSX is stricter, because every tag must be closed in one of the two ways. Suppose you forget the slash on an Image in the card:
<View> <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}> <Text>Sara</Text> </View>
The parser treats the Text as a child of the Image, so the closing tags no longer match the opening tags, and the build stops. When this card is inside a complete component, the message is the following:
Unterminated JSX contents.
This message does not mention the Image, and its line number points to the closing View tag rather than to the tag that caused it. When you see it, check the tags above that line for a missing slash or closing tag. In other cases, the parser reports Expected corresponding JSX closing tag for <Image>, which names the tag directly.
Why Developers Prefer the Short Form
Writing <Image></Image> works, but it adds a closing tag that carries no information. A reader seeing an opening and closing pair expects something between them, and has to look to confirm that nothing is there. The short form also means one fewer tag to mismatch. Developers use it as a standard practice, so <Image></Image> in React Native code looks unusual to other readers.
Finishing the Profile Card
Some components are nearly always self-closing, because all of their information comes from props. Here is the finished card with four of them:
import { ActivityIndicator, Image, Text, TextInput, View } from 'react-native'; export default function ProfileCard() { return ( <View style={{ padding: 16, backgroundColor: '#eef6f6' }}> <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} style={{ width: 64, height: 64 }} /> <Text style={{ fontSize: 24 }}>Sara</Text> <Text>4 of 5 correct</Text> <View style={{ flexDirection: 'row' }}> <Text>Quizzes: 3</Text> <Text>Streak: 7</Text> </View> <View style={{ height: 1, backgroundColor: '#cccccc' }} /> <TextInput placeholder="Add a note" /> <ActivityIndicator size="large" /> </View> ); }
View Image Text: Sara Text: 4 of 5 correct View Text: Quizzes: 3 Text: Streak: 7 View TextInput ActivityIndicator
Long self-closing tags can span several lines, as the Image does here, with the slash on the last line.
Image displays a picture, and its source prop says which one. An image loaded from a URL must have a width and a height in its style, because React Native does not know the size of a network image in advance. Without those two values, the image does not appear, even though the code runs without an error. Image also cannot have children. Its source code throws the error The <Image> component cannot contain children if you try, and the message suggests ImageBackground for placing content on top of a picture. That component is now deprecated, and the Styling chapter shows its replacement.
View usually wraps other elements, as the statistics row does, but the second inner View has no children and acts as a thin divider line. Its size and color come entirely from its style, so it needs no content.
TextInput is the field where the user types, and its text comes from props and from the keyboard rather than from children. Web developers sometimes write Input, but React Native has no such component. Importing it gives undefined, and rendering it stops with Element type is invalid.
ActivityIndicator is a loading spinner. It shows the platform's spinner, and its size prop is "small" by default or "large" as in this card.
Reading Progress
0%
On This Page
Why JSX Requires the Slash
Why Developers Prefer the Short Form
Finishing the Profile Card