Explain what makes React treat a function as a component (element type), the JSX naming rule (Uppercase vs lowercase), what it must return, and the practical rules around calling it (don’t call directly if it uses Hooks). Include common runtime errors and gotchas. Uppercase naming and hook rules are common edge cases, so add tests for warnings and invalid returns.
What rules must a function follow to be treated as a React component?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Core idea
React treats a function as a component when you use it as an element type: <MyComp /> (or React.createElement(MyComp)). Then React calls it during rendering and interprets its return value as UI.
Rule | What it means | Why it matters |
|---|---|---|
Use it as an element type | Render it as | If you just call |
Uppercase name in JSX |
| Lowercase tags are treated as DOM elements ( |
Return a valid React node | Return JSX, string/number, fragment, array of nodes, | Returning an invalid type (like a plain object or Promise) crashes at runtime. |
Be render-safe (no side effects in render) | Component body should compute UI; side effects go to effects/handlers | Render can run multiple times (StrictMode / concurrent scheduling). |
// ✅ Component: uppercase usage
function Hello({ name }) {
return <h1>Hello {name}</h1>;
}
export default function App() {
return <Hello name="Ada" />;
}
// ❌ Not a component in JSX: lowercase means DOM tag
function hello() {
return <h1>hi</h1>;
}
export function Broken() {
return <hello />; // React treats this as <"hello"> DOM element, not your function.
}
Return value | Allowed? | Notes |
|---|---|---|
JSX element | ✅ | Most common: |
string / number | ✅ | Renders a text node |
| ✅ | Renders nothing (intentional gating) |
Array of nodes | ✅ | Use keys for stable lists |
Plain object | ❌ | Error: |
Promise (async function) | ❌ (client) | Async component returns a Promise; not a valid React node in client rendering |
// ❌ Invalid return
function Bad() {
return { ok: true }; // runtime error
}
// ✅ Valid: render nothing
function Gate({ enabled }) {
if (!enabled) return null;
return <div>Enabled</div>;
}
Hooks-specific rule
If the function uses Hooks, it must be treated as a real component: call it only via React render (<Comp />), and follow the Rules of Hooks (call hooks at the top level, not inside conditions/loops). Calling a Hook-using component like Comp() is a common mistake.
function Counter() {
const [n, setN] = React.useState(0);
return <button onClick={() => setN((x) => x + 1)}>{n}</button>;
}
// ❌ Don’t do this
function Wrong() {
const el = Counter(); // breaks Hooks model
return <div>{el}</div>;
}
// ✅ Do this
function Right() {
return <Counter />;
}
Practical scenario
You create a reusable UserCard component and render it in a list with JSX.
Common pitfalls
- Using a lowercase name so React treats it as a DOM tag.
- Calling the function directly instead of using JSX, breaking hook rules.
- Returning invalid values or fragments without a wrapper.
Component naming and hook rules are strict but predictable. Test for warnings in dev and add lint rules.
A function is treated as a React component when React sees it as the element type (<MyComp /> / createElement(MyComp)), it’s capitalized in JSX, and it returns a valid React node. If it uses Hooks, it must only be invoked by React’s render pipeline (not called directly).