This blog post summarizes the concept of React components.
- How to define a component in React.
- JSX: Write it right.
- Props and State in components.
- Conditional Rendering.
- Composition - The pillar of React.
In React, there are two ways to define a component: Class components and Function components.
Componentis the base class for React components defined as JavaScript classes.
At the beginning of the React.dev - Component page, there's a warning:
"We recommend defining components as functions instead of classes. See how to migrate."
Why does React recommend using Function components for new applications? Let’s first understand Class components and their pitfalls.
Class components are essentially JavaScript classes designed for rendering React components. The Class component has 29 references, and you can dive into each on the React.dev documentation. Here's an example to illustrate:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => this.setState({ count: this.state.count + 1 });
render() {
return <button onClick={this.increment}>{this.state.count}</button>;
}
}We created a simple Counter component with just one button. But look at the number of lines required to make it functional! As applications grow, so do the challenges of using Class components: managing lifecycle methods, reusing logic, handling this, and dealing with boilerplate-heavy code.
To resolve these issues, the React team introduced Hooks, allowing Function components to manage state and side effects. Hooks provide all the functionality of Class components (and more), making them the standard for modern React applications.
import React from 'react';
const Counter = () => {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
};Wow! With just a few lines of code, we’ve built the same component using a Function component. No need for classes, constructors, or this.
- Simpler Syntax and Readability:
- Function components are cleaner and easier to understand, especially for beginners.
- Reusability with Hooks:
- Hooks like
useStateanduseEffectmake it easier to reuse logic without restructuring components.
- Hooks like
- Avoiding Complexity from
this:- Function components eliminate the need to manage
thisbindings.
- Function components eliminate the need to manage
- Performance Benefits:
- Function components are faster as they don’t need to instantiate a class.
- Easier to Test:
- Function components are simpler to test since they are plain functions.
- Modern Ecosystem Alignment:
- React’s modern tools and features are optimized for Function components.
Do You Need to Migrate All Class Components? Not necessarily! While Function components are preferred for new development, existing Class components are still supported. Migrate only when modernizing or refactoring your code.
Reference: https://www.robinwieruch.de/react-function-component/
JSX is a combination of HTML and JavaScript, known as JavaScript XML. For example:
<button onClick={() => setCount(count + 1)}>{count}</button>JSX represents the UI of React components, resembling HTML but with stricter rules:
- Return a single root element:
return <div><h1>Hello!</h1></div>;
- Close all tags:
<img src="image.jpg" alt="description" />
- Use
camelCasefor attributes:<button onClick={...} className="btn">Click Me</button>
Reference: https://react.dev/learn/writing-markup-with-jsx
State represents the "memory" of a component. For example:
const Counter = () => {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
};Here, count is the state of the Counter component, managed using useState.
Reference: https://react.dev/learn/state-a-components-memory
Props (short for "properties") allow you to pass data from parent to child components. For example:
const Counter = ({ className, children }) => {
const [count, setCount] = React.useState(0);
return (
<div>
{children}
<button className={className} onClick={() => setCount(count + 1)}>
{count}
</button>
</div>
);
};Reference: https://www.robinwieruch.de/react-pass-props-to-component/
Use JavaScript’s conditional operators to render components conditionally:
const Counter = () => {
const [count, setCount] = React.useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count === 0 ? "Zero" : count}
</button>
);
};Reference: https://www.robinwieruch.de/conditional-rendering-react/
React allows nesting components within others, making it highly composable:
const Avatar = ({ src, alt }) => <img src={src} alt={alt} />;
const Profile = () => (
<div>
<Avatar src="https://picsum.photos/200" alt="Profile Picture" />
</div>
);Reference: https://react.dev/learn/passing-props-to-a-component#passing-jsx-as-children
This blog covered the basics of React components, explaining their types, JSX rules, state, props, and conditional rendering. It also highlighted why Function components are preferred in modern React development. Keep these principles in mind as you build scalable and maintainable React applications.