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