DailyDevDiet

logo - dailydevdiet

Learn. Build. Innovate. Elevate your coding skills with dailydevdiet!

Chapter 5: React Components

React Components

Introduction to React Components

Components are the building blocks of any React application. They are reusable pieces of code that return React elements describing what should appear on the screen. In essence, components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

Why Components?

Components offer several advantages:

  1. Reusability: Write once, use anywhere in your application
  2. Maintainability: Smaller, focused pieces of code are easier to maintain
  3. Separation of concerns: Each component handles a specific part of the UI
  4. Testability: Individual components can be tested in isolation

Types of Components

React provides two types of components:

1. Function Components

Function components are the simpler way to define a component. They are JavaScript functions that accept props (properties) as an argument and return React elements.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

2. Class Components

Class components are ES6 classes that extend from React.Component and require a render method that returns React elements.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Component Structure

Let’s examine the anatomy of a React component:

Import Statements

At the top of your component file, you typically import React and any other dependencies:

import React from 'react';
import './ComponentName.css'; // Optional CSS file

Component Declaration

Next comes the component declaration, either as a function or class:

function ComponentName(props) {
  // Component logic
  return (
    // JSX for UI
  );
}

Export Statement

Finally, you export the component to make it available for import in other files:

export default ComponentName;

Creating Your First Component

Let’s create a simple component step by step:

// Button.js
import React from 'react';

function Button(props) {
  return (
    <button className="custom-button">
      {props.label}
    </button>
  );
}export default Button;

This Button component can be used in other components like this:

import Button from './Button';

function App() {
  return (
    <div>
      <h1>My App</h1>
      <Button label="Click Me" />
    </div>
  );
}

Component Composition

Components can contain other components. This concept is called composition and is a powerful feature of React.

function Page() {
  return (
    <div>
      <Header />
      <MainContent />
      <Footer />
    </div>
  );
}

function Header() {
  return <header>This is the header</header>;
}

function MainContent() {
  return <main>This is the main content</main>;
}

function Footer() {
  return <footer>This is the footer</footer>;
}

Component Best Practices

1. Keep Components Small and Focused

Each component should do one thing well. If a component becomes too complex, consider breaking it down into smaller components.

2. Use Meaningful Names

Name your components according to what they do, not what they look like:

  • Good: ProductList, UserProfile, PaymentForm
  • Bad: BlueBox, LeftPanel, BigComponent

3. Separate Container and Presentational Components

  • Container Components: Focus on how things work (data fetching, state management)
  • Presentational Components: Focus on how things look (UI, styling)

4. Create Component Folders

For larger applications, organize components in folders with related files:

/components
  /Button
    Button.js
    Button.css
    Button.test.js

Pure Components

A pure component is one that always renders the same output for the same props and state. React provides a React.PureComponent for class components and React.memo() for function components to optimize rendering performance.

import React, { memo } from 'react';

const PureButton = memo(function Button(props) {
  return <button>{props.label}</button>;
});

export default PureButton;

For class components:

import React, { PureComponent } from 'react';

class PureButton extends PureComponent {
  render() {
    return <button>{this.props.label}</button>;
  }
}

export default PureButton;

Fragments

React Fragments let you group a list of children without adding extra nodes to the DOM:

function Table() {
  return (
    <table>
      <tbody>
        <Row />
      </tbody>
    </table>
  );
}

function Row() {
  return (
    <React.Fragment>
      <td>Hello</td>
      <td>World</td>
    </React.Fragment>
  );
}

// Short syntax
function RowShort() {
  return (
    <>
      <td>Hello</td>
      <td>World</td>
    </>
  );
}

Component Communication

Components can communicate with each other through props, context, and state management libraries. We’ll cover more complex communication patterns in later chapters.

Dynamic Components with Props

Components can render dynamically based on the props they receive:

function Alert(props) {
  const { type, message } = props;
 
  const alertClasses = {
    success: 'alert-success',
    warning: 'alert-warning',
    error: 'alert-error'
  };
 
  return (
    <div className={`alert ${alertClasses[type] || 'alert-info'}`}>
      {message}
    </div>
  );
}

// Using the component
function App() {
  return (
    <div>
      <Alert type="success" message="Operation completed successfully!" />
      <Alert type="error" message="Something went wrong!" />
    </div>
  );
}

Conditional Rendering

Components can render different UI elements based on conditions:

function UserGreeting(props) {
  const { isLoggedIn } = props;
 
  // Method 1: If-Else
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  } else {
    return <h1>Please sign in</h1>;
  }
 
  // Method 2: Ternary Operator
  // return (
  //   <h1>
  //     {isLoggedIn ? 'Welcome back!' : 'Please sign in'}
  //   </h1>
  // );
 
  // Method 3: Logical && Operator
  // return (
  //   <div>
  //     {isLoggedIn && <h1>Welcome back!</h1>}
  //     {!isLoggedIn && <h1>Please sign in</h1>}
  //   </div>
  // );
}

Rendering Lists

Components can render lists of items using JavaScript’s map() function:

function ProductList(props) {
  const { products } = props;
 
  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>
          {product.name} - ${product.price}
        </li>
      ))}
    </ul>
  );
}

// Using the component
function App() {
  const productData = [
    { id: 1, name: 'Laptop', price: 999 },
    { id: 2, name: 'Phone', price: 699 },
    { id: 3, name: 'Tablet', price: 399 }
  ];
 
  return <ProductList products={productData} />;
}

Note: Always use the key prop when rendering lists. Keys help React identify which items have changed, been added, or been removed.

Practical Example: Creating a Card Component

Let’s create a practical Card component that can be reused throughout an application:

// Card.js
import React from 'react';
import './Card.css';

function Card(props) {
  const { title, image, description, actions } = props;
 
  return (
    <div className="card">
      {image && (
        <div className="card-image">
          <img src={image} alt={title} />
        </div>
      )}
     
      <div className="card-content">
        {title && <h2 className="card-title">{title}</h2>}
        {description && <p className="card-description">{description}</p>}
      </div>
     
      {actions && (
        <div className="card-actions">
          {actions}
        </div>
      )}
    </div>
  );
}

export default Card;

Usage example:

function App() {
  return (
    <div className="app">
      <Card
        title="Getting Started with React"
        image="https://example.com/react-logo.png"
        description="Learn the fundamentals of React in this comprehensive guide."
        actions={
          <>
            <button>Read More</button>
            <button>Save</button>
          </>
        }
      />
    </div>
  );
}

Summary

In this chapter, we’ve covered:

  • The concept of components as building blocks of React applications
  • Two types of components: Function and Class components
  • Component structure and creation
  • Component composition
  • Component best practices
  • Pure components for optimization
  • React Fragments to avoid unnecessary DOM nodes
  • Dynamic rendering with props
  • Conditional rendering techniques
  • Rendering lists with keys
  • A practical Card component example

Components form the foundation of React development. In the next chapter, we’ll dive deeper into the concepts of State and Props, which will allow us to create more dynamic and interactive components.

Exercises

  1. Create a Button component that accepts props for label, color, and onClick function
  2. Build a UserProfile component that displays a user’s name, email, and profile picture
  3. Create a TabPanel component with a Tab component that handles switching between different content panels
  4. Build a Card component similar to the example but add additional features like badges or tags
  5. Create a component hierarchy for a blog post page (hint: think about Header, Post, Comments, Sidebar, etc.)

Additional Resources

Scroll to Top