← Back to React
Lesson 11 · Components and Props

Functional Components

A component is a function that returns UI. Everything else follows.

Beginner35 min

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

The smallest component, and using it
function Welcome() { return <h1>Welcome to React</h1>; } function App() { return ( <div> <Welcome /> </div> ); }
Before: one long page
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> ); }
After: the same page, composed
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> ); }
The component tree it builds
CoursePage ├── CourseHeader ├── CourseProgress ├── ModuleList │ ├── ModuleCard │ └── ModuleCard └── CourseFooter Both ModuleCards say "React Fundamentals" - props, next lesson, fix that.
Components are functions: variables, helpers, early returns
// 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%
React.FC is optional - and no longer adds children
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>; }
Mistake: calling a component as a function
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.
Mistake: defining a component inside another
// 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" />; }
Keep render pure
// 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>; }
A common file layout
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

PascalCase

Capitalised names are components; lowercase are DOM elements.

function CourseCard()
Returns UI

JSX, text, a number, null, or an array of these.

return <article />;
Used as a tag

React calls it. Never call it yourself.

<CourseCard />
Top-level only

Never define a component inside another.

function A() {}
function B() {}
Pure render

Same inputs, same output, no side effects.

// no fetch() in the body
One per file

Named 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.

Extract three

“Take the long CoursePage and extract CourseHeader, CourseProgress, and CourseFooter one at a time, checking the page looks identical after each step.”

Lowercase it

“Rename CourseHeader to courseHeader everywhere. What appears in the Elements panel, and what does the console say?”

Call it

“Build the Counter example with {show && Counter()} and click Toggle. Then change it to {show && <Counter />}.”

Nest it

“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

A lowercase component name

Lowercase tags are DOM elements, so React creates an unknown element and never calls your function.

✗ function courseCard() { ... }
<courseCard />
✓ function CourseCard() { ... }
<CourseCard />
Calling a component as a function

Its hooks run as part of the parent. Called conditionally, that changes the hook count and crashes the app.

✗ {show && Counter()}
✓ {show && <Counter />}
Defining a component inside another

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 />;
}
Side effects while rendering

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 course
One enormous component

A 1,000-line App is hard to read, change, and test. Extract sections with a clear job.

A component for every tag

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.

1.

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 hint

Four small functions, then one that renders all four inside a main.

Show 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> ); }
2.

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 hint

Header is the parent; Logo and Navigation are its children.

Show 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 // └── Navigation
3.

Find the two bugs: function Page() { function Banner() { return <p>Sale!</p>; } return <div>{Banner()}<Footer /></div>; }

Show hint

One is about where Banner is defined, the other about how it is used.

Show 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> ); }
Coding challenge

A course page, composed

Build the full component structure of a course page with static content - composition only, no data yet.

It should
  • 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 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

What three things make a function a component?
A capitalised name, a return value React can render, and being used as a JSX tag so React calls it.
Why is {Counter()} risky when <Counter /> is not?
Called as a function, its hooks run as part of the parent. If the call is conditional, the parent hook count changes between renders and React throws.
What goes wrong when a component is defined inside another?
Each render creates a new function, so React treats it as a new component type, remounts it, and its state is lost.
Why must rendering be pure?
React calls components whenever it needs the UI - on every re-render and twice in development - so side effects in the body would repeat unpredictably.

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. 1.

    Which is a valid React component? A. function courseCard() { return <div />; } B. function CourseCard() { return <div />; }

  2. 2.

    How do you normally render a component? A. CourseCard() B. <CourseCard />

  3. 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. 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. 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...