React Components
Components are the fundamental building blocks of any React application. They allow you to split the UI into independent, reusable, and isolated pieces of code. Understanding how to create, manage, and compose components is critical to mastering React.
Functional vs. Class Components
Historically, React had two distinct ways of writing components. While modern React focuses almost entirely on functional components, understanding the distinction is important for working with legacy codebases.
Class Components
Class components are ES6 classes that extend React.Component. They were traditionally the only way to manage state and utilize lifecycle methods.
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
console.log("Component mounted");
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}
Functional Components
Functional components are simply JavaScript functions that accept props and return React elements. With the introduction of Hooks in React 16.8, functional components can now manage state and side effects, rendering class components largely obsolete for new development.
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Component mounted");
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
Why Functional Components?
- Less Boilerplate: No
thisbindings orconstructorsetup. - Better Minification: Classes are harder for bundlers to minify.
- Hooks Reusability: Custom hooks allow for easier sharing of stateful logic compared to Higher-Order Components (HOCs) or render props.
Pure Components and React.memo
React components re-render when their state or props change. Sometimes, a component re-renders even when its props haven't changed, simply because its parent re-rendered.
To optimize performance, we can use "pure" components. A pure component only re-renders if its props strictly change (shallow comparison).
For class components, you extend React.PureComponent:
class MyComponent extends React.PureComponent { /* ... */ }
For functional components, you wrap the component in React.memo:
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
Use memoization judiciously. The cost of comparing props might sometimes outweigh the cost of a simple re-render. It is best used on heavy components that receive the same props frequently.
Component Composition
React has a powerful composition model. Instead of using inheritance to create specialized components, React recommends using composition.
Containment
Some components don't know their children ahead of time. Examples include Sidebar or Dialog generic "boxes". These components can use the special children prop to pass children elements directly into their output.
function Card({ children }) {
return (
<div className="card-wrapper shadow-lg p-4">
{children}
</div>
);
}
function App() {
return (
<Card>
<h1 className="title">Welcome</h1>
<p>This content is passed as children.</p>
</Card>
);
}
Specialization
Sometimes we think about components as being "special cases" of other components. For example, a WelcomeDialog might be a special case of Dialog. In React, this is also achieved by composition, where a more specific component renders a more generic one and configures it with props.
function Dialog({ title, message }) {
return (
<div className="dialog">
<h2>{title}</h2>
<p>{message}</p>
</div>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome to our App"
message="We are glad to have you here!"
/>
);
}
Conclusion
Mastering components—knowing when to create them, how to keep them pure, and how to compose them effectively—is the key to building scalable and maintainable React applications. Emphasize functional components with hooks, and use composition to keep your UI modular.