
Components: The Reusable Unit
A component is a JavaScript function that returns UI. Modern React is built almost entirely from function components rather than the older class component syntax, which is no longer the starting point for new code.function ProductCard({ name, price }) {
return (
{name}
${price}
);
}
// Used like this, as many times as needed:
The entire point of a component is reuse: write the UI logic once, then render it with different inputs anywhere it’s needed.Props: Data Flowing In, One Direction
Props (short for properties) are how a parent component passes data down to a child. They work exactly like function arguments — read-only from the child’s perspective, and the child cannot modify its own props directly.function App() {
const user = { name: 'Amara', role: 'Admin' };
return ;
}
function UserBadge({ name, role }) {
// name and role are read-only here — UserBadge cannot change them
return {name} ({role});
}This one-directional flow — data only moves from parent to child, never the reverse — is deliberate and is what makes React applications predictable to debug: a value can only have changed because whoever owns it changed it, not because some distant child component reached back and mutated it.

State: Data a Component Owns and Can Change
State is data that belongs to a component and can change over time — a form input’s current value, whether a modal is open, a counter’s current count. Unlike props, a component fully controls its own state and updates it with the useState hook:function LikeButton() {
const [liked, setLiked] = useState(false);
return (
);
}Calling setLiked doesn’t just update a variable — it tells React to re-render the component with the new value, which is the mechanism that makes the UI actually reflect the change on screen.How the Three Work Together: Lifting State Up
A common early confusion is what to do when two sibling components both need access to the same piece of changing data. The answer is a pattern called “lifting state up”: move the state to their shared parent, then pass it down to both children as props, along with a function (also passed as a prop) that lets a child request a change.function ShoppingCart() {
const [items, setItems] = useState([]);
return (
<>
setItems([...items, item])} />
>
);
}
// State lives in ShoppingCart. ProductList triggers changes via onAdd (a prop).
// CartSummary just reads the current items (also a prop). Neither owns the state itself. This pattern — state living as high as necessary but no higher, passed down through props, changed only through functions the owner explicitly hands out — is the actual architectural skill in React. Almost every confusing React bug in a real codebase traces back to state living in the wrong place, not to a misunderstanding of the useState syntax itself.