Functional Components
Functional components are the standard way to write React components. They are JavaScript functions that accept props and return JSX describing what should appear on screen.
Every component you write in a modern React project should be a functional component. The older class-based approach is still supported, but hooks have replaced the need for it in almost every situation.
A basic functional component
function Hello() {
return <h1>Hello, world!</h1>;
}
export default Hello;
That is a complete component. It is a function, it returns JSX, and its name starts with a capital letter.
You can also write it as an arrow function:
const Hello = () => {
return <h1>Hello, world!</h1>;
};
export default Hello;
Both forms are fine. The function keyword is common for top-level components; arrow functions are common for small helper components. Pick a style and be consistent.
Props: passing data into a component
Props (short for properties) let a parent component send data to a child component. They work like HTML attributes.
function Greeting(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Used in a parent:
<Greeting name="Alice" />
This renders: Hello, Alice!
Destructuring props
Most developers destructure props directly in the function signature. It is cleaner and easier to read:
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
Both approaches produce identical results. Destructuring is the more common pattern in modern React code.
Default prop values
You can set a default value for a prop using standard JavaScript default parameters:
function Greeting({ name = 'World' }) {
return <h1>Hello, {name}!</h1>;
}
// Using the default:
<Greeting /> // renders: Hello, World!
// Overriding the default:
<Greeting name="Alice" /> // renders: Hello, Alice!
The children prop
When you write content between a component’s opening and closing tags, React passes that content as a special prop called children:
function Card({ children }) {
return <div className="card">{children}</div>;
}
// Used in a parent:
<Card>
<h2>Card Title</h2>
<p>Some description text here.</p>
</Card>
The children prop is how you build wrapper components: layouts, modals, panels, and so on.
Prop types
For large projects, you may want to document and enforce what types of props a component expects.
- PropTypes: a runtime check that logs a warning when wrong types are passed. Install with
npm install prop-types. - TypeScript: a compile-time check. If your project uses TypeScript, you can type props directly in the function signature.
For smaller projects or when just learning, neither is required. They become more useful as a codebase grows.
Composing components
The real power of components is composition: building complex UIs from small, focused pieces.
Here is a Card component with a title, description, and children:
function Card({ title, description, children }) {
return (
<div className="card">
<h2>{title}</h2>
<p>{description}</p>
{children}
</div>
);
}
And a page that uses several cards:
function App() {
return (
<main>
<Card title="Getting Started" description="How to set up your project.">
<a href="/setup">Read the guide</a>
</Card>
<Card title="Components" description="The building blocks of React." />
<Card title="Hooks" description="Add state and effects to functional components." />
</main>
);
}
Each card is independent. If you want to change how a card looks, you change the Card component and every card updates.
A complete example
Here is a small product listing UI built from composed components:
function Badge({ label }) {
return <span className="badge">{label}</span>;
}
function ProductCard({ name, price, inStock }) {
return (
<div className="product-card">
<h3>{name}</h3>
<p>${price}</p>
{inStock ? (
<Badge label="In Stock" />
) : (
<Badge label="Out of Stock" />
)}
</div>
);
}
function ProductList({ products }) {
return (
<div className="product-list">
{products.map((product) => (
<ProductCard
key={product.id}
name={product.name}
price={product.price}
inStock={product.inStock}
/>
))}
</div>
);
}
export default ProductList;
Three components, each with one job. ProductList renders a list. ProductCard renders one card. Badge renders a label. None of them know about each other except through props.
Common mistakes
Mutating props directly.
Props are read-only. A component should never modify the props it receives.
// Wrong: mutating a prop
function UserProfile({ user }) {
user.name = 'Changed'; // do not do this
return <p>{user.name}</p>;
}
// Correct: use the prop as-is, or derive new values from it
function UserProfile({ user }) {
const displayName = user.name.toUpperCase();
return <p>{displayName}</p>;
}
If you need to track changing data, that is what state is for.
Calling a component as a function instead of using JSX.
// Wrong: this skips React's rendering pipeline
const result = MyComponent();
// Correct: let React render it
const result = <MyComponent />;
Forgetting to pass a required prop.
If a component expects a name prop and you do not pass one, you will get undefined in the rendered output. Use default values or PropTypes to catch this early.
FAQ
What is the difference between props and state?
Props are passed in from the outside (from a parent component). They are read-only inside the component that receives them. State is data that a component manages internally and can change over time. When state changes, the component re-renders. See React State for more.
Why can’t I modify props?
React’s rendering model relies on data flowing in one direction: from parent to child. If a child could modify props, it would be harder to understand where data comes from and predict how the app behaves. If you need to change something, either lift the state up to the parent or use local state inside the component.
Can I pass functions as props?
Yes. Passing functions as props is how child components communicate back to their parents. For example:
function Button({ onClick, label }) {
return <button onClick={onClick}>{label}</button>;
}
function App() {
function handleClick() {
console.log('Button was clicked');
}
return <Button onClick={handleClick} label="Click me" />;
}
The Button component does not need to know what handleClick does. It just calls the function it was given.
What to learn next
- React State : how to add data that changes over time to a component
- React Hooks : the tools that make functional components powerful
- React Components : a broader overview of how components fit together