Functional Components
A component is a function that returns UI. Everything else follows.
What you will be able to do
- Explain what a component is, and what makes a function a component
- Write, name, and use a functional component
- Compose a page from smaller components, and draw its component tree
- Extract a component from a large one - and know when not to
- Explain why components must be pure while rendering
- Avoid calling a component as a function, and defining one inside another
The idea, in plain English
A component is a reusable piece of UI. In modern React it is simply a JavaScript function that returns JSX: function Welcome() { return <h1>Welcome to React</h1>; }. Use it as a tag - <Welcome /> - and React calls the function and puts what it returns on the page.
Components are how React applications are built. A course page is not one enormous block of markup; it is a CourseHeader, a CourseProgress, a ModuleList made of ModuleCards, and a CourseFooter. Each is small enough to understand on its own, and the page is just those pieces arranged together. That arrangement is called composition.
Because a component is a function, everything you know about functions applies: it can hold variables, do calculations, call helpers, and return early. The one rule React adds is that rendering must be pure - given the same inputs, a component returns the same UI and does nothing else.
The components in this lesson always show the same content. Props, from the next lesson on, are what let one CourseCard show React, TypeScript, or Node.js.
Worked example: Turning one long course page into focused components.
What makes a function a component
Three things. Its name starts with a capital letter. It returns something React can render - JSX, a string, a number, null, or an array of those. And it is used as a JSX tag, <Welcome />, so that React is the one calling it.
The capital letter is not style. JSX compiles lowercase tags to strings, which become DOM elements, and capitalised tags to a reference to your function. <courseCard /> creates an unknown <coursecard> element and never calls your function; React warns "is using incorrect casing".
Name components in PascalCase after what they are: CourseCard, LessonList, UserProfile. A good name tells the reader what the component shows without opening it.
You do not need React.FC
Older code often declares components as const CourseCard: React.FC = () => ... . It still works, but it adds nothing. Since React 18 the FC type no longer includes children, and a plain function with typed parameters is the style React itself uses.
Write components as ordinary functions. When props arrive in the next lesson, you type the parameter: function CourseCard({ title, lessons }: CourseCardProps). Arrow functions - const CourseCard = () => ... - are fine too; pick one style and keep it.
Composition and the component tree
A component can render other components, which render others. App renders CoursePage; CoursePage renders CourseHeader, ModuleList, and CourseFooter; ModuleList renders ModuleCards. Building UI by combining components like this is composition.
The result is a tree, with App at the root. The component that renders another is its parent, and the one rendered is its child. The tree is the single most useful picture of a React app: data will flow down it (props), and events will flow up it (callbacks) - both later in this module.
Draw the tree before you write the code. Boxes on a sketch of the page become components; boxes inside boxes become children.
Extracting a component
Components usually start big and get split. When a section of a large component has a clear job - the header, the progress bar, the module list - move its JSX into a new function with a descriptive name, and render that function in its place. That is component extraction.
The page gets shorter and reads like a table of contents: <CourseHeader />, <CourseProgress />, <ModuleList />. Each extracted piece can be read, changed, and tested without scrolling past the rest.
When to make a component - and when not to
Good reasons: the UI is repeated, a section has its own behaviour, a section is complex enough to deserve a name, or extracting it makes the parent read better.
Bad reasons: every element must be a component, or files should be small for their own sake. A CourseTitle that wraps one h1 and is used once adds a file and a name, and removes nothing. Components should mark meaningful boundaries - CourseHeader, ModuleList - not wrap individual tags.
Components are functions: logic included
Above the return you can declare variables, compute values, call helper functions, and return early. A CourseProgress can compute a percentage; a CourseStatus can return one thing when the course is complete and another when it is not.
Helpers that do not use anything from the component belong outside it - a formatLessons(count) function at the top of the file is created once, can be tested alone, and keeps the component short.
Rendering must be pure
React calls your component whenever it needs the UI - once on the first render, again on every re-render, and twice in development under StrictMode. So the function must only calculate what to show. Given the same inputs, it returns the same JSX, and it changes nothing outside itself.
fetch("/api/courses"), localStorage.setItem, or analytics calls in the body of a component would run on every render - twice in development, and at times you do not control. Side effects belong in event handlers and in useEffect, both later in this course.
Two mistakes that break components
Calling a component as a function. {CourseCard()} renders the same markup as <CourseCard /> - until the component uses a hook. Then its state belongs to the parent instead of to itself, and calling it conditionally changes the number of hooks the parent runs. React throws "Rendered more hooks than during the previous render" and the whole app goes blank. Always use the tag, and let React do the calling.
Defining a component inside another. function App() { function SearchBox() { ... } return <SearchBox />; } creates a brand-new SearchBox function on every render of App. React sees a different component type each time, throws the old one away, and mounts a new one - so anything typed into its input disappears whenever App re-renders. Define every component at the top level of a file.
Watch out: Both mistakes work in simple tests and fail later - the first when the component gets a hook, the second when the parent gets state. Both were reproduced for this lesson in React 19.
Syntax and examples
function Welcome() {
return <h1>Welcome to React</h1>;
}
function App() {
return (
<div>
<Welcome />
</div>
);
}function CoursePage() {
return (
<main>
<header>
<h1>React Complete Course</h1>
<p>18 Modules · 192 Lessons</p>
</header>
<section>
<h2>Progress</h2>
<p>40%</p>
</section>
<section>
<h2>Modules</h2>
<article>
<h3>React Fundamentals</h3>
<p>10 lessons</p>
</article>
<article>
<h3>Components and Props</h3>
<p>10 lessons</p>
</article>
{/* ... and 16 more modules */}
</section>
<footer>
<p>Happy learning!</p>
</footer>
</main>
);
}function CourseHeader() {
return (
<header>
<h1>React Complete Course</h1>
<p>18 Modules · 192 Lessons</p>
</header>
);
}
function CourseProgress() {
return (
<section>
<h2>Progress</h2>
<p>40%</p>
</section>
);
}
function ModuleCard() {
return (
<article>
<h3>React Fundamentals</h3>
<p>10 lessons</p>
</article>
);
}
function ModuleList() {
return (
<section>
<h2>Modules</h2>
<ModuleCard />
<ModuleCard />
</section>
);
}
function CourseFooter() {
return (
<footer>
<p>Happy learning!</p>
</footer>
);
}
function CoursePage() {
return (
<main>
<CourseHeader />
<CourseProgress />
<ModuleList />
<CourseFooter />
</main>
);
}CoursePage
├── CourseHeader
├── CourseProgress
├── ModuleList
│ ├── ModuleCard
│ └── ModuleCard
└── CourseFooter
Both ModuleCards say "React Fundamentals" - props, next lesson, fix that.// A helper that needs nothing from the component lives outside it
function formatLessons(count: number) {
return `${count} lessons`;
}
function CourseSummary() {
const title = "React Complete Course";
const modules = 18;
const lessons = 192;
return (
<section>
<h1>{title}</h1>
<p>{modules} modules · {formatLessons(lessons)}</p>
</section>
);
}
function CourseStatus() {
const completed = 8;
const total = 10;
if (completed === total) {
return <p>Completed</p>;
}
return <p>Progress: {(completed / total) * 100}%</p>;
}
// Progress: 80%import type { FC } from "react";
// Works, but adds nothing
const CourseCard: FC = () => <article>React</article>;
// Since React 18, FC does not include children:
const Card: FC = ({ children }) => <div>{children}</div>;
// error TS2339: Property 'children' does not exist on type '{}'.
// Preferred: a plain function
function CourseCard2() {
return <article>React</article>;
}function Counter() {
const [count, setCount] = useState(0); // a hook - Module 3
return <button onClick={() => setCount(count + 1)}>Count {count}</button>;
}
function App() {
const [show, setShow] = useState(false);
return (
<div>
<button onClick={() => setShow(!show)}>Toggle</button>
{/* Click Toggle: the whole app goes blank */}
{show && Counter()}
</div>
);
}
// Rendered more hooks than during the previous render.
//
// Fix: {show && <Counter />} - React calls it, and it owns its own state.// Wrong: a new SearchBox type on every render of App
function App() {
const [count, setCount] = useState(0);
function SearchBox() {
return <input placeholder="Search courses" />;
}
return (
<>
<SearchBox />
<button onClick={() => setCount(count + 1)}>Clicked {count}</button>
</>
);
}
// Type "react", click the button - the input is empty again.
// Right: define it once, at the top level
function SearchBox() {
return <input placeholder="Search courses" />;
}// Wrong: runs on every render - twice in development
function CoursePage() {
fetch("/api/courses");
localStorage.setItem("visited", "true");
return <h1>Courses</h1>;
}
// Right: render only calculates. Side effects go in event handlers
// or useEffect, both covered later in the course.
function CoursePage() {
return <h1>Courses</h1>;
}src/
├── components/ reusable pieces
│ ├── CourseCard.tsx
│ ├── ModuleCard.tsx
│ └── LessonCard.tsx
├── pages/ whole screens, composed from components
│ ├── HomePage.tsx
│ └── CoursePage.tsx
├── App.tsx
└── main.tsx
One component per file, file named after the component,
exported as default or named - be consistent.Tip: Before writing a new page, sketch it and draw boxes around each part. Every box that has a clear name - header, progress, module list - is a component, and boxes inside boxes are its children.
Component rules
PascalCaseCapitalised names are components; lowercase are DOM elements.
function CourseCard()
Returns UIJSX, text, a number, null, or an array of these.
return <article />;
Used as a tagReact calls it. Never call it yourself.
<CourseCard />
Top-level onlyNever define a component inside another.
function A() {}
function B() {}Pure renderSame inputs, same output, no side effects.
// no fetch() in the body
One per fileNamed after the component it exports.
CourseCard.tsx
Try it yourself
The code does not change. Swap the content string and the program does something else entirely.
“Take the long CoursePage and extract CourseHeader, CourseProgress, and CourseFooter one at a time, checking the page looks identical after each step.”
“Rename CourseHeader to courseHeader everywhere. What appears in the Elements panel, and what does the console say?”
“Build the Counter example with {show && Counter()} and click Toggle. Then change it to {show && <Counter />}.”
“Define SearchBox inside App, type into it, and click a button that updates App state. Move SearchBox to the top level and try again.”
What usually goes wrong
Lowercase tags are DOM elements, so React creates an unknown element and never calls your function.
✗ function courseCard() { ... }
<courseCard />✓ function CourseCard() { ... }
<CourseCard />Its hooks run as part of the parent. Called conditionally, that changes the hook count and crashes the app.
✗ {show && Counter()}✓ {show && <Counter />}Every render creates a new component type, so React remounts it and its state is lost.
✗ function App() {
function SearchBox() { ... }
return <SearchBox />;
}✓ function SearchBox() { ... }
function App() {
return <SearchBox />;
}The body runs on every render, and twice in development. Requests and storage writes do not belong there.
✗ function CoursePage() {
fetch("/api/courses");
return <h1>Courses</h1>;
}✓ // fetch in an event handler or useEffect - later in the courseA 1,000-line App is hard to read, change, and test. Extract sections with a clear job.
Wrapping a single h1 used once in its own component adds a file and removes nothing. Components should mark meaningful boundaries.
Best practices
- Name components in PascalCase after what they show.
- Write components as plain functions; skip React.FC.
- Define every component at the top level of a file, one component per file.
- Extract a component when a section is reused, complex, or has its own job.
- Keep rendering pure - calculate UI, nothing else.
- Sketch the component tree before writing a new page.
Practice
Write these yourself before opening anything. Getting them wrong first is most of how this sticks.
Build a CoursePage from four components: CourseHeader ("React Complete Course" and "18 Modules • 192 Lessons"), CourseProgress ("Progress: 40%"), ModuleList (React Fundamentals, Components and Props, State and Events), and CourseFooter ("Happy Learning!").
Show hintHide hint
Four small functions, then one that renders all four inside a main.
Show solutionHide solution
function CourseHeader() {
return (
<header>
<h1>React Complete Course</h1>
<p>18 Modules • 192 Lessons</p>
</header>
);
}
function CourseProgress() {
return <p>Progress: 40%</p>;
}
function ModuleList() {
return (
<section>
<h2>Modules</h2>
<ul>
<li>React Fundamentals</li>
<li>Components and Props</li>
<li>State and Events</li>
</ul>
</section>
);
}
function CourseFooter() {
return (
<footer>
<p>Happy Learning!</p>
</footer>
);
}
function CoursePage() {
return (
<main>
<CourseHeader />
<CourseProgress />
<ModuleList />
<CourseFooter />
</main>
);
}Write a Header composed of a Logo (the text "RTE") and a Navigation with links to /courses, /paths, and /resources. Then draw its component tree.
Show hintHide hint
Header is the parent; Logo and Navigation are its children.
Show solutionHide solution
function Logo() {
return <div>RTE</div>;
}
function Navigation() {
return (
<nav>
<a href="/courses">Courses</a>
<a href="/paths">Learning Paths</a>
<a href="/resources">Resources</a>
</nav>
);
}
function Header() {
return (
<header>
<Logo />
<Navigation />
</header>
);
}
// Header
// ├── Logo
// └── NavigationFind the two bugs: function Page() { function Banner() { return <p>Sale!</p>; } return <div>{Banner()}<Footer /></div>; }
Show hintHide hint
One is about where Banner is defined, the other about how it is used.
Show solutionHide solution
// 1. Banner is defined inside Page - a new component type every render.
// 2. Banner is called as a function instead of used as a tag.
function Banner() {
return <p>Sale!</p>;
}
function Page() {
return (
<div>
<Banner />
<Footer />
</div>
);
}A course page, composed
Build the full component structure of a course page with static content - composition only, no data yet.
- CoursePage renders CourseHeader, CourseProgress, ModuleList, and CourseFooter.
- ModuleList renders three ModuleCards.
- Each ModuleCard renders a heading and a LessonList.
- Each LessonList renders three LessonCards, each with a title, a duration, and a Start Lesson button.
- Every component is defined at the top level and used as a tag.
- Write the component tree as a comment at the top of the file.
// CoursePage
// ├── CourseHeader
// ├── CourseProgress
// ├── ModuleList
// │ └── ModuleCard (x3)
// │ └── LessonList
// │ └── LessonCard (x3)
// └── CourseFooter
function LessonCard() {
// start here, and work up the tree
}Show one solutionHide solution
function LessonCard() {
return (
<article>
<h4>JSX Expressions</h4>
<p>30 minutes</p>
<button>Start Lesson</button>
</article>
);
}
function LessonList() {
return (
<div>
<LessonCard />
<LessonCard />
<LessonCard />
</div>
);
}
function ModuleCard() {
return (
<section>
<h3>React Fundamentals</h3>
<LessonList />
</section>
);
}
function ModuleList() {
return (
<section>
<h2>Modules</h2>
<ModuleCard />
<ModuleCard />
<ModuleCard />
</section>
);
}
function CourseHeader() {
return (
<header>
<h1>React Complete Course</h1>
<p>18 Modules · 192 Lessons</p>
</header>
);
}
function CourseProgress() {
return <p>Progress: 40%</p>;
}
function CourseFooter() {
return <footer>Happy learning!</footer>;
}
function CoursePage() {
return (
<main>
<CourseHeader />
<CourseProgress />
<ModuleList />
<CourseFooter />
</main>
);
}
// Every card is identical - 9 copies of "JSX Expressions".
// That is the problem props solve.Key points
- A component is a function that returns UI, named in PascalCase and used as a tag.
- Lowercase tags are DOM elements; capitalised tags are your components.
- A plain function is enough - React.FC adds nothing and no longer types children.
- Pages are built by composing components; the result is a component tree.
- Extract components at meaningful boundaries, not for every tag.
- Components can hold variables, helpers, and early returns.
- Rendering must be pure: same inputs, same output, no side effects.
- Never call a component as a function, and never define one inside another.
Quick check before you move on
Interview questions
What is a functional component?
A JavaScript function that returns React elements, usually as JSX. React calls it when it needs that part of the UI and renders what it returns.
Why must component names start with a capital letter?
JSX compiles lowercase tags to strings, which become DOM elements, and capitalised tags to a reference to the function. A lowercase component would be treated as an unknown HTML element.
What is component composition?
Building larger UI by rendering components inside other components. A page is a tree of components, each responsible for one part.
Should you use React.FC?
It is not needed. A plain function with a typed props parameter is simpler, and since React 18 FC no longer includes children, so it offers little.
Why should you not call a component as a function?
React would not see it as a component. Its hooks would belong to the caller, so a conditional call changes the caller hook order and throws, and it gets no identity of its own for state or keys.
Why not define a component inside another component?
The inner function is recreated on every render, so React sees a new component type each time, unmounts the old one, and mounts a new one - losing its state and DOM, and wasting work.
When should you extract a component?
When a piece of UI is reused, has its own behaviour, is complex enough to deserve a name, or extracting it makes the parent easier to read. Not for every element.
Quiz
- 1.
Which is a valid React component? A. function courseCard() { return <div />; } B. function CourseCard() { return <div />; }
- 2.
How do you normally render a component? A. CourseCard() B. <CourseCard />
- 3.
function App() { return (<><Header /><Content /><Footer /></>); } What does this show? A. Component composition B. A database relationship C. CSS inheritance D. API routing
- 4.
What is the purpose of splitting UI into components? A. Make every HTML element a separate file B. Create meaningful, reusable, maintainable units C. Avoid JavaScript D. Remove JSX
- 5.
A SearchBox is defined inside App. What happens to its typed text when App re-renders? A. It is kept B. It is lost C. It moves to another input D. React throws
Comments
Sign in to leave a comment. Your name and photo come from Google; nothing else is shared.
Loading comments...
AI
System Design
Backend
- GraphQL8 modules · 69 lessons planned
- Core Python13 modules · 75 lessons planned
- FastAPI5 sections · 20 lessons
- Node.js14 modules · 206 lessons planned
- Node.js Performance7 chapters · 36 topics
- Event Loop Lifecycle6 phases · 3 scenarios
- Docker & Containerization11 modules · 144 lessons planned
- AWS for Developers14 modules · 219 lessons planned
- CI/CD & DevOps Automation10 modules · 134 lessons planned