Function Components — The Building Blocks of React

A React component is a JavaScript function that returns JSX describing a piece of the user interface. That is it — nothing more exotic is required. You write a function, it returns some markup, and React handles the rest. The power comes from the fact that these functions are composable: small, focused components are combined into larger ones, which are combined into pages, which together form your entire application. In this lesson you will learn exactly what makes a valid React component, the naming rules React enforces, and how to build the MERN Blog UI by composing simple components into complex structures.

What Makes a Valid React Component

// ── Minimal valid component ───────────────────────────────────────────────────
function Greeting() {
  return <h1>Hello, MERN!</h1>;
}

// ── Component returning null — renders nothing ────────────────────────────────
function HiddenWhenEmpty({ items }) {
  if (items.length === 0) return null;
  return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}

// ── Arrow function component ───────────────────────────────────────────────────
const PostCard = ({ title }) => <div className="card"><h2>{title}</h2></div>;

// ── Component returning multiple elements via Fragment ─────────────────────────
function AuthButtons() {
  return (
    <>
      <button>Login</button>
      <button>Register</button>
    </>
  );
}
Note: React identifies a component vs a plain HTML element by the first letter of its name. Capitalised names are components (<PostCard />). Lowercase names are HTML elements (<div>, <p>). This is why component names must always start with a capital letter — if you name a component postCard and write <postCard />, React will treat it as an unknown HTML element and render nothing visible while silently failing.
Tip: One component per file is the standard convention in React. Name the file the same as the component: PostCard.jsx exports function PostCard. This makes it trivial to find any component in the codebase, enables clean import paths (import PostCard from '@/components/PostCard'), and ensures your editor’s file search and component search give the same results.
Warning: Never define a component inside another component’s function body. Each render of the outer component creates a brand new function reference for the inner component, forcing React to unmount and remount it from scratch on every re-render — destroying all its internal state. Always define components at the top level of a file, not inside other components.

Component Naming Rules

Rule Correct Wrong
Must start with capital letter PostCard postCard
PascalCase convention UserProfileAvatar userProfileAvatar, User_Profile
Descriptive noun or noun phrase PostList, LoginForm DoStuff, HandleThings
File name matches component name PostCard.jsx exports function PostCard post-card.jsx with mismatched name

Composing Components

// Small, focused components composed into larger ones

function Avatar({ src, name }) {
  return <img className="avatar" src={src} alt={name} />;
}

function Badge({ label, variant = 'default' }) {
  return <span className={`badge badge--${variant}`}>{label}</span>;
}

function PostCard({ post }) {
  return (
    <article className="post-card">
      <div className="post-card__meta">
        <Avatar src={post.author.avatar} name={post.author.name} />
        <span>{post.author.name}</span>
      </div>
      <h2 className="post-card__title">{post.title}</h2>
      <p>{post.excerpt}</p>
      <div className="post-card__tags">
        {post.tags.map(tag => <Badge key={tag} label={tag} variant="tag" />)}
      </div>
    </article>
  );
}

function HomePage({ posts }) {
  return (
    <main>
      <h1>Latest Posts</h1>
      {posts.map(post => <PostCard key={post._id} post={post} />)}
    </main>
  );
}

Export Patterns

// Default export — one per file
export default function PostCard({ post }) {
  return <article>...</article>;
}
// Import: import PostCard from '@/components/PostCard'

// Named export — multiple exports per file
export function PostCard({ post }) { return ... }
export function PostList({ posts }) { return ... }
// Import: import { PostCard, PostList } from '@/components/posts'

// Barrel re-export
// components/index.js
export { default as PostCard } from './PostCard';
export { default as PostList } from './PostList';
export { default as Spinner }  from './Spinner';
// Import: import { PostCard, Spinner } from '@/components'

Common Mistakes

Mistake 1 — Lowercase component name

❌ Wrong — React treats lowercase as an HTML element:

function postCard({ post }) { return <div>{post.title}</div>; }
// <postCard post={...} /> → renders <postcard> (unknown HTML) — nothing visible

✅ Correct — always start with a capital letter:

function PostCard({ post }) { return <div>{post.title}</div>; }
// <PostCard post={...} /> → correct ✓

Mistake 2 — Defining a component inside another component

❌ Wrong — inner component recreated every render:

function PostList({ posts }) {
  function Row({ post }) { return <li>{post.title}</li>; } // re-created every render!
  return <ul>{posts.map(p => <Row key={p._id} post={p} />)}</ul>;
}

✅ Correct — define at module top level:

function PostRow({ post }) { return <li>{post.title}</li>; }  // top-level ✓
function PostList({ posts }) {
  return <ul>{posts.map(p => <PostRow key={p._id} post={p} />)}</ul>;
}

Mistake 3 — Using a component without importing it

❌ Wrong — forgetting to import:

// Missing import Spinner
function PostPage() {
  if (loading) return <Spinner />; // ReferenceError: Spinner is not defined
}

✅ Correct:

import Spinner from '@/components/Spinner'; // ✓

Quick Reference

Task Code
Define component function PostCard() { return <div>...</div>; }
Arrow component const PostCard = () => <div>...</div>;
Default export export default function PostCard() { ... }
Use a component <PostCard />
Return nothing return null;
Multiple roots return <><A /><B /></>;

🧠 Test Yourself

You define function postCard() { return <div>Post</div>; } and use it as <postCard />. You see an empty browser but no JavaScript error. Why?