Your first component
Write a React component: a function that returns markup. Learn why its name needs a capital letter, nest components, and move them into their own files.
- 01Write a componentDefine a function with a capital letter that returns markup, export it, and avoid the bare
returnthat makes it show nothing. - 02Nest componentsUse components inside other components, and say what the browser really receives: only the HTML tags they return.
- 03Split components into filesMove a component into its own file and import it, with a default or a named export, and fix an import that doesn't match.
A piece of the page with a name
In Why React? you saw that React builds a page out of components: pieces like a header, a product card, or a cart. This lesson is about writing them. Here is the smallest component there is. Its result is live, under the code:
export default function WelcomeBanner() { return <h1>Welcome to the tea shop</h1>;}Line 1 makes a function named WelcomeBanner. Line 2 is its only job: it returns <h1>Welcome to the tea shop</h1>, markup that looks like HTML, and React shows that heading on the page. That's all a component is: a JavaScript function that returns markup. Press Edit & run, change the words between <h1> and </h1>, and watch the heading follow as you type.
WelcomeBanner is a function. It returns markup, an <h1>, and React puts that heading on the page.The markup inside a component is called JSX. It looks like HTML but it's part of your JavaScript; the next lesson, Writing markup with JSX, covers its rules. In this lesson, the JSX is plain tags like <h1>, <p>, and <article>.
A shop owner carves a rubber stamp of the shop's logo once. After that, every bag, receipt, and loyalty card gets the logo with one press. If the logo changes, she carves a new stamp, and every new print changes with it.
- In real life: Carving the stamp once
- In React: Writing
function TeaCard() { … }once - In real life: The name on its handle
- In React: The component's name, starting with a capital letter
- In real life: Pressing it on the paper, as often as you like
- In React: Writing
<TeaCard />wherever you want a card - In real life: Only ink lands on the paper, never the stamp
- In React: Only HTML tags reach the page, never the component
A React component is a JavaScript function that returns markup. Its name starts with a capital letter, and you use it like a tag, <WelcomeBanner />, as many times as you like. React calls the function and puts the markup it returns on the page.
Writing a component, line by line
A real component usually returns more than one tag. Here is a card for one tea on a shop's menu. The example has two files, in tabs: App.jsx with the component, and styles.css, which draws the card's border.
export default function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> <p>Fresh leaves from the hills.</p> <p>$3</p> </article> );}It has three parts, one per job:
- Export it.
export defaulton line 1 is plain JavaScript, not React. It marksTeaCardas this file's main export, so another file can import it, and so the live result knows what to show. - Define the function.
function TeaCard()on line 1 is an ordinary function declaration. Its name starts with a capital letter; the next section shows why that matters. - Return the markup. Lines 2 to 8 return one
<article>holding a heading and two paragraphs (lines 3 to 7).classNameon line 3 is how JSX spells HTML'sclass; the next lesson explains why.
The round brackets on lines 2 and 8 matter. When the markup takes several lines, open a bracket on the same line as return. Here is what happens without one:
function TeaCard() { return <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article>;} export default function App() { return ( <section> <h2>Today's teas</h2> <TeaCard /> </section> );}The result shows the heading from line 12, Today's teas, and no card. App (lines 9 to 16) uses TeaCard on line 13; the section after next explains how that works. The bug is on line 2: return stands alone. JavaScript ends a return statement at the end of its line when nothing follows it there (the semicolons lesson explains this rule), so TeaCard returns undefined and lines 3 to 6 never run. React shows nothing for a component that returns undefined, and no error tells you. Press Edit & run and change line 2 to return (, then add a line with ); after line 6, in place of its ;. The card appears.
A component can also be an arrow function stored in a constant. React treats it the same way. This course uses function declarations, as React's own documentation does:
const TeaCard = () => (
<article className="tea-card">
<h3>Green tea</h3>
</article>
);Line 1 stores the function in TeaCard. The brackets on lines 1 and 5 hold the markup the arrow function returns. It isn't exported, so this block has no result of its own.
Capital letters: your component or an HTML tag
React components must start with a capital letter. This is the rule beginners break most, so here is what happens when you don't follow it:
function teaCard() { return <p>Green tea, $3</p>;} export default function App() { return ( <section> <h2>Today's teas</h2> <teaCard /> </section> );}Line 1 defines a function named teaCard, and line 9 uses <teaCard />. The result shows only the heading. Nothing crashed, but React never called teaCard. A tag that starts with a small letter is a tag name for the browser, like <section> or <h2>, even when a function by that name exists. So the page got an element called <teacard>: an unknown tag with nothing inside. Press Edit & run to see the console. React warns about line 9 twice:
<teaCard /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.The tag <teaCard> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
PascalCase means every word starts with a capital letter, as in TeaCard and ShopHeader. React needs only the first letter to be a capital; the rest is a habit every React project shares. Fix the example: rename the function on line 1 to TeaCard and the tag on line 9 to <TeaCard />. The card appears, and the warnings go away.
<TeaCard /> means your function, and React calls it. With a small letter, <teaCard /> is only a tag name, so the browser gets an empty <teacard>.The reason is in how JSX works. Before your code runs, each tag becomes a function call that tells React what to make. For a tag with a small first letter, that call gets the tag's name as text, "section", and the browser makes the element. For a capital letter, it gets your function itself, TeaCard, and React calls it. The next lesson shows those calls, compiled by a real compiler.
How to read this table: each row is a tag you might write, what React takes it to mean, and what ends up on the page.
| When you write | React reads it as | What you get |
|---|---|---|
<section> | A small first letter: a tag name for the browser. | The browser's own <section> element. |
<TeaCard /> | A capital letter: the function named TeaCard in your code. | React calls TeaCard, and its <article> goes on the page. |
<teaCard /> | A small first letter: a tag name, even though your function has this name. | An empty, unknown <teacard> element, and two warnings in the console. |
<Teacard /> | A capital letter: a function named Teacard, which doesn't exist. | An error, Teacard is not defined, because the name must match exactly. |
Components inside components
Components get useful when they use each other. A menu page has a header and some tea cards. Each is its own component, and a third one, MenuPage, puts them together:
function ShopHeader() { return ( <header> <h1>Asha's Tea Shop</h1> </header> );} function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article> );} export default function MenuPage() { return ( <main> <ShopHeader /> <TeaCard /> <TeaCard /> <TeaCard /> </main> );}Lines 1 to 7 define ShopHeader, which returns a <header> with the shop's name. Lines 9 to 16 define TeaCard. MenuPage (lines 18 to 27) returns a <main> that uses <ShopHeader /> once, on line 21, and <TeaCard /> three times, on lines 22 to 24. The result shows the heading and three cards. They're all the same tea for now; the Passing props to a component lesson shows how to give each card its own.
MenuPage is the parent of ShopHeader and the cards, and they are its children. A tag like <TeaCard /> that has nothing inside it ends with />, which closes it. MenuPage is the one with export default, so it's the component this file gives to whoever imports it, and the one the live result shows. Press Edit & run and copy line 24 twice: five cards. Delete line 21: the header goes.
So what does the browser get? It never sees MenuPage or TeaCard: those are your functions. React calls each one, and only the HTML tags they return reach the page.
<header> from ShopHeader and an <article> for each TeaCard.Try it below. The buttons change how many cards MenuPage uses, and Use ShopHeader adds or removes ShopHeader. React renders the page right here, and the last box is the page's real HTML, read back from the page after every change.
function ShopHeader() { return ( <header> <h1>Asha's Tea Shop</h1> </header> );} function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article> );} export default function MenuPage() { return ( <main> <ShopHeader /> <TeaCard /> <TeaCard /> <TeaCard /> </main> );}5 componentsAsha's Tea Shop
Green tea
$3
Green tea
$3
Green tea
$3
Choose how many TeaCards MenuPage uses, and whether it uses ShopHeader.
With three cards and the header, you used 5 components, and the HTML has 12 elements: <main>, the <header> and its <h1>, and an <article>, <h3>, and <p> for each card. Not one component name. Notice className became the HTML attribute class. Turn off Use ShopHeader, and the <header> and its <h1> leave the HTML.
One rule comes with nesting: use components inside other components, but always define them at the top level of the file, as in the menu page. Never write one function component inside another:
export default function MenuPage() {
// Don't: a new TeaCard function every time MenuPage runs
function TeaCard() {
return <article className="tea-card">Green tea</article>;
}
return <TeaCard />;
}It looks tidy, and the page even looks right. But every time MenuPage runs, lines 3 to 5 make a brand-new TeaCard function. React compares components by the function itself, so it sees a different component every time: it removes that part of the page and builds it again from scratch, losing anything the card remembered, like text typed into a box. It's slow and causes bugs that are hard to find. The Preserving and resetting state lesson shows it happening. Keep TeaCard above MenuPage, as the menu page does.
Moving a component into its own file
One file with every component gets long. React projects usually give each bigger component its own file, named after it. Moving one takes three steps:
- Make a new file, such as
TeaCard.jsx. - Move the component there and export it.
- Import it in the file that uses it.
Here is the result. Click the tabs to read both files:
import TeaCard from "./TeaCard.jsx"; export default function App() { return ( <main> <h1>Asha's Tea Shop</h1> <TeaCard /> <TeaCard /> </main> );}In TeaCard.jsx, line 1 exports the component with export default. In App.jsx, line 1 imports it: import TeaCard from "./TeaCard.jsx";. The ./ means "in the same folder as this file". Lines 7 and 8 use it twice, exactly as if it were written in App.jsx. Many projects leave off the .jsx, as in "./TeaCard"; their build tool finds the file either way.
TeaCard.jsx exports its component, and App.jsx imports it by the file's name. Then <TeaCard /> works in App as if it were written there.App.jsx is the root component file: the one at the top of the tree, holding the component that the whole page starts from. Every live example on this site has one more file that hands App to React, as you saw in Why React? (Pop out shows it). In a framework like Next.js, each page of the site has its own root component instead.
A file can also export more than one thing. JavaScript has two kinds of exports, which you met in The JavaScript you need for React: a default export, at most one per file, and named exports, as many as you like. Here Menu.jsx has both:
import Menu, { TeaCard } from "./Menu.jsx"; export default function App() { return ( <main> <h2>Today's pick</h2> <TeaCard /> <Menu /> </main> );}In Menu.jsx, line 1 is a named export, export function TeaCard(), and line 10 is the default export, Menu. In App.jsx, line 1 imports both at once: Menu without braces for the default export, and { TeaCard } in braces for the named one. Line 7 shows one card as today's pick, and line 8 shows the whole menu.
How to read this table: each row asks the same question of both kinds of export.
| Question | Default export | Named export |
|---|---|---|
| How do you export it? | export default function TeaCard() {} | export function TeaCard() {} |
| How do you import it? | import TeaCard from "./TeaCard.jsx"; | import { TeaCard } from "./TeaCard.jsx"; |
| How many can one file have? | One at most. | As many as you like. |
| Which name do you write on import? | Any name; it gets the default export. | The exact name it was exported with. |
| When do people use it? | For the one main component of a file. | When a file shares several components or values. |
The import must match the export. Ask for a named export the file doesn't have, and the page can't start at all. Line 1 here uses braces, but TeaCard.jsx only has a default export:
import { TeaCard } from "./TeaCard.jsx"; export default function App() { return ( <main> <h1>Asha's Tea Shop</h1> <TeaCard /> </main> );}The result shows the browser's own error, SyntaxError, with the full address the preview gives the file: The requested module '…/TeaCard.jsx' does not provide an export named 'TeaCard'. The browser checks every import before any of the code runs, so nothing shows, not even the heading on line 6. Press Edit & run and remove the braces on line 1; the page comes back. Try every pairing in the playground below: it runs two small files as real modules in your browser.
export default function TeaCard() { return "Green tea";}import TeaCard from "./TeaCard.js"; console.log(TeaCard());running…
Running the two files…
Matching pairs print Green tea. A default export with braces fails with does not provide an export named 'TeaCard', and a named export without braces fails with does not provide an export named 'default'. A common habit: a default export when a file has one main component, and named exports when it shares several. Whichever you choose, give the component a name. An unnamed one, like export default () => …, has no name of its own: error messages and React's developer tools show it as default or Anonymous, which makes bugs harder to find.
Splitting a real page into components
Real pages often start as one long component. This shop page works, but everything is in App: the header, two tea cards, and the footer.
export default function App() { return ( <main> <header> <h1>Asha's Tea Shop</h1> <p>Open every day, 8 to 6</p> </header> <section> <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article> <article className="tea-card"> <h3>Mint tea</h3> <p>$4</p> </article> </section> <footer> <p>12 Park Street</p> </footer> </main> );}Lines 4 to 7 are the header, lines 8 to 17 a section with the two cards, and lines 18 to 20 the footer. To change how every card looks, you edit both copies. To use the header on a second page, you copy it. Look for parts with a name of their own, like "the header" or "the tea list", and make each one a component:
import ShopHeader from "./ShopHeader.jsx";import TeaList from "./TeaList.jsx";import ShopFooter from "./ShopFooter.jsx"; export default function App() { return ( <main> <ShopHeader /> <TeaList /> <ShopFooter /> </main> );}Now App.jsx reads like a table of contents: lines 1 to 3 import three components, and lines 8 to 10 put them in order. Each tab holds one of them. TeaList.jsx keeps two small components, GreenTea and MintTea, without exporting them: only TeaList uses them, so they stay in that file. The page looks the same, and the browser gets the same HTML. Open the ShopFooter.jsx tab in Edit & run and change the address: only the footer changes.
<TeaCard /><article><ShopHeader /><header><button><SearchBox /><img src="tea.png" /><CartIcon />
Sort each tag: does React call a function you wrote, or does the browser make the element itself?
Common mix-ups
- "A component is a special object that React makes." No. It's an ordinary JavaScript function that you write. React only calls it. (Older code also writes components as classes; React still runs them, but new code uses functions.)
- "The browser sees my <TeaCard> tag." No. Component names never reach the page. The browser gets only the HTML tags your components return, as the playground shows.
- "A small first letter is fine if the function exists." No.
<teaCard />is read as an HTML tag name, so React never calls your function and the page gets an empty<teacard>. - "A file can hold only one component." No. It can have one default export, any number of named exports, and components it keeps to itself, like
GreenTeainTeaList.jsx. - "Every file with JSX needs
import React from "react"." Not any more. Since React 17, the build adds what JSX needs by itself. You import fromreactonly what you use by name, likeuseState. None of this lesson's files import React. - "Defining a component inside another keeps it private and tidy." No. It makes a new component every time the outer one runs, so React rebuilds it from scratch. Define components at the top level, and leave them unexported to keep them private.
Practice exercises
Each exercise shows its code's result under it, or when you press Edit & run. Change the code, and the result updates as you type. Try a guess first, then use the hints.
How many tea cards does this page show? Answer first, then press Edit & run to check.
function TeaCard() {
return (
<article className="tea-card">
<h3>Green tea</h3>
</article>
);
}
function TeaShelf() {
return (
<section>
<TeaCard />
<TeaCard />
</section>
);
}
export default function App() {
return (
<main>
<TeaCard />
<TeaShelf />
<TeaCard />
</main>
);
}function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> </article> );} function TeaShelf() { return ( <section> <TeaCard /> <TeaCard /> </section> );} export default function App() { return ( <main> <TeaCard /> <TeaShelf /> <TeaCard /> </main> );}App shows a card on line 21, then TeaShelf, which holds two cards (lines 12 and 13), then one more card on line 23. That's 4 cards, and the HTML has 4 <article> elements.
The page shows only the heading. Fix the component so the cake card appears. What does the card's heading say?
function cakeCard() { return ( <article className="tea-card"> <h3>Lemon cake</h3> <p>$4</p> </article> );} export default function App() { return ( <main> <h2>Cakes</h2> <cakeCard /> </main> );}function CakeCard() { return ( <article className="tea-card"> <h3>Lemon cake</h3> <p>$4</p> </article> );} export default function App() { return ( <main> <h2>Cakes</h2> <CakeCard /> </main> );}With a small c, <cakeCard /> is an HTML tag name, so the page gets an empty <cakecard>. With a capital C, React calls your function, and the card shows Lemon cake.
The tea card is missing, and there's no error. Find the bug and fix it. What does the card's heading say?
function TeaCard() { return <article className="tea-card"> <h3>Mint tea</h3> <p>$4</p> </article>;} export default function App() { return ( <main> <h2>Today's teas</h2> <TeaCard /> </main> );}function TeaCard() { return ( <article className="tea-card"> <h3>Mint tea</h3> <p>$4</p> </article> );} export default function App() { return ( <main> <h2>Today's teas</h2> <TeaCard /> </main> );}A bare return ends the statement at the end of its line, so TeaCard returned undefined and React showed nothing for it. With the bracket opened on the return line, the whole <article> is returned, and the card shows Mint tea.
Write a ShopFooter component that shows Open every day, 8 to 6 in a <footer>, and use it under the card. What does the last line of the page say?
function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article> );} export default function App() { return ( <main> <TeaCard /> </main> );}function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article> );} function ShopFooter() { return ( <footer> <p>Open every day, 8 to 6</p> </footer> );} export default function App() { return ( <main> <TeaCard /> <ShopFooter /> </main> );}ShopFooter (lines 10 to 16) is a component like any other: a capitalized function that returns markup. App uses it on line 22, after the card, so the page ends with Open every day, 8 to 6.
Move TeaCard into the TeaCard.jsx tab with a default export, and import it in App.jsx. What line do you add at the top of App.jsx?
function TeaCard() { return ( <article className="tea-card"> <h3>Green tea</h3> <p>$3</p> </article> );} export default function App() { return ( <main> <h1>Asha's Tea Shop</h1> <TeaCard /> </main> );}import TeaCard from "./TeaCard.jsx"; export default function App() { return ( <main> <h1>Asha's Tea Shop</h1> <TeaCard /> </main> );}TeaCard.jsx now holds the component with export default, and line 1 of App.jsx imports it. The page looks exactly the same: moving a component changes where its code lives, not what it shows.
Press Edit & run: this page shows an error instead of the shop. Fix line 1 of App.jsx without changing TeaCard.jsx. What should line 1 be?
import TeaCard from "./TeaCard.jsx";
export default function App() {
return (
<main>
<h1>Asha's Tea Shop</h1>
<TeaCard />
</main>
);
}import { TeaCard } from "./TeaCard.jsx"; export default function App() { return ( <main> <h1>Asha's Tea Shop</h1> <TeaCard /> </main> );}TeaCard.jsx has export function TeaCard(), a named export, and no default export. An import without braces asks for the default one, so the browser stops. import { TeaCard } from "./TeaCard.jsx"; asks for the export by its name, and the page shows the card.
Check your understanding
For code questions, find each component first, then follow the tags from the exported one. Press Edit & run on a question's code to check your answer.
Question 1 of 8What is a React component?
Choose an answer to see the explanation.
Question 2 of 8What does this shop page show?
Read the code, then predictfunction TeaCard() { return <article>Green tea</article>; } function ShopHeader() { return <h1>Asha's Tea Shop</h1>; } export default function App() { return ( <main> <ShopHeader /> <TeaCard /> <TeaCard /> <TeaCard /> </main> ); }Choose an answer to see the explanation.
Question 3 of 8Which of these functions can you use as a tag, like
<…/>, in JSX?Choose an answer to see the explanation.
Question 4 of 8What does this page show, with
returnalone on line 2?Read the code, then predictfunction Banner() { return <h1>Welcome to the tea shop</h1>; } export default function App() { return ( <main> <Banner /> <p>Open every day</p> </main> ); }Choose an answer to see the explanation.
Question 5 of 8
MenuPagereturns a<main>that uses<TeaCard />, andTeaCardreturns an<article>. Which tags reach the browser's page?Choose an answer to see the explanation.
Question 6 of 8SoldOutBadge.jsx holds this code. Which line imports it?
Read the code, then predictJSXexport function SoldOutBadge() { return <span>Sold out</span>; }Choose an answer to see the explanation.
Question 7 of 8How many default exports can one file have?
Choose an answer to see the explanation.
Question 8 of 8Why shouldn't you define one component inside another component's function?
Choose an answer to see the explanation.
Key takeaways
- A React component is a JavaScript function that returns markup. You use it like a tag, as often as you like.
- Its name must start with a capital letter.
<TeaCard />calls your function;<teaCard />is only a tag name for the browser. - When the markup takes several lines, open a bracket on the
returnline. A barereturnreturns nothing. - Components use other components, forming a tree. The browser gets only the HTML tags they return, never their names.
- Define every component at the top level of its file, never inside another component.
- Move a component into its own file with
export defaultandimport X from "./X.jsx", or a named export and an import with braces. The import must match the export.
Remember the one-liner.
A component is a capitalized function that returns markup; write it once, use it like a tag anywhere.
Coming next: Writing markup with JSX. It shows what each tag turns into, and why JSX has rules like one root element, closed tags, and className.