Components & Props
Function components take read-only props flowing parent→child; use children, defaults, spread, and Context to avoid drilling.
Function components#
A component is a function that takes a props object and returns React elements. Names must be PascalCase — lowercase names are treated as DOM tags.
function Avatar({ src, alt }) {
return <img className="avatar" src={src} alt={alt} />;
}
// Usage — JSX attributes become the props object
<Avatar src={user.url} alt={user.name} />
Props are read-only 🎯#
Props are immutable inside the receiving component. A component must never mutate its own props — that breaks the UI = f(props, state) contract and one-way data flow. Treat props like function arguments: read them, don't reassign them.
function Total({ items }) {
items.push(1); // ⚠️ NEVER mutate props — breaks parent's data
return <b>{items.length}</b>;
}
One-way flow (parent → child)#
Data flows down. To let a child affect the parent, pass a callback prop; the child calls it, the parent owns the state ("lifting state up").
function Parent() {
const [q, setQ] = useState("");
return <Search value={q} onChange={setQ} />; // data down, events up
}
function Search({ value, onChange }) {
return <input value={value} onChange={e => onChange(e.target.value)} />;
}
children#
children is a special prop holding whatever you nest between a component's tags — the basis of composition and generic wrappers.
function Card({ title, children }) {
return (
<section className="card">
<h3>{title}</h3>
<div className="body">{children}</div>
</section>
);
}
<Card title="Profile">
<Avatar src={u.url} alt={u.name} /> {/* becomes children */}
<p>{u.bio}</p>
</Card>
Default values via destructuring 🟢#
Set defaults right in the parameter list (modern replacement for the legacy defaultProps, which is deprecated for function components in React 19).
function Button({ variant = "primary", disabled = false, children }) {
return <button className={variant} disabled={disabled}>{children}</button>;
}
Spreading props#
{...props} forwards a whole object — useful for pass-through wrappers, but ⚠️ use deliberately: spreading unknown props onto DOM elements can leak invalid attributes.
function Input(props) {
return <input className="field" {...props} />; // forwards value, onChange, etc.
}
Prop drilling → Context#
Passing a prop through many intermediate components that don't use it is prop drilling. It's fine for shallow trees; for deep or cross-cutting data (theme, auth, locale) use Context (see the Context topic) or a state library.
flowchart TD
App["App (owns user)"] -->|"user"| Page["Page"]
Page -->|"user"| Toolbar["Toolbar (doesn't use it)"]
Toolbar -->|"user"| Menu["UserMenu (finally uses it)"]
App -.->|"Context avoids the middle hops"| Menu
Interview Q&A#
Q1. Are props mutable? No. Props are read-only inside the component. A component must never modify its own props; mutation breaks one-way data flow and can corrupt the parent's state.
Q2. How does a child update state owned by a parent? The parent passes a callback prop; the child invokes it with new data. The parent updates its own state — this is "lifting state up."
Q3. What is the children prop?
A built-in prop holding whatever JSX is nested between a component's opening and closing tags, enabling composition and wrapper components.
Q4. How do you set default prop values in modern React?
Use default values in destructuring, e.g. function Btn({ size = "md" }). defaultProps on function components is deprecated as of React 19.
Q5. What is prop drilling and how do you avoid it?
Passing props through intermediate components that don't need them. Avoid it with Context, component composition (passing children), or a state-management library.