DEV Community

Cover image for Understanding Components, Props, and State Management in React
John Schibelli
John Schibelli

Posted on • Originally published at schibelli.dev

Understanding Components, Props, and State Management in React

This is the third installment in the Mastering React Fundamentals series. In the previous articles, we covered the basics of React and JSX. Now, we take a deeper dive into components, props, and state—essential concepts that make React applications dynamic and modular.

Introduction

React is built around the concept of components, which are the building blocks of any React application. Components allow developers to create reusable UI elements, making applications modular and maintainable. To manage and pass data between these components, React introduces props and state.

In this article, we will explore:

  • The difference between functional and class components

  • How to pass data using props

  • Managing component state effectively

  • Best practices for working with components, props, and state


Understanding Components

In React, a component is a JavaScript function or class that returns a React element (JSX). Components can be broadly categorized into functional components and class components.

Functional Components

Functional components are simple JavaScript functions that take in props as arguments and return JSX. These are widely used with React Hooks for state and lifecycle management.

Example of a Functional Component:

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

export default Greeting;
Enter fullscreen mode Exit fullscreen mode

You can use this component inside another component:

import Greeting from './Greeting';

function App() {
  return (
    <div>
      <Greeting name="Alice" />
      <Greeting name="Bob" />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Class Components (Deprecated in Modern React)

Before React Hooks, class components were the primary way to handle state and lifecycle methods. They are still supported but are being phased out in favor of functional components.

import React, { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default Greeting;
Enter fullscreen mode Exit fullscreen mode

Props in React

Props (short for properties) are a way to pass data from a parent component to a child component. Props are read-only, meaning they cannot be modified inside the child component.

Using Props in a Component:

function Welcome(props) {
  return <h1>Welcome, {props.username}!</h1>;
}

function App() {
  return (
    <div>
      <Welcome username="JohnDoe" />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Default Props

You can set default values for props to ensure a component functions correctly even if a prop is not passed:

function Welcome(props) {
  return <h1>Welcome, {props.username}!</h1>;
}

Welcome.defaultProps = {
  username: 'Guest'
};
Enter fullscreen mode Exit fullscreen mode

Prop Types

To enforce prop validation, you can use PropTypes:

import PropTypes from 'prop-types';

function Welcome(props) {
  return <h1>Welcome, {props.username}!</h1>;
}

Welcome.propTypes = {
  username: PropTypes.string
};
Enter fullscreen mode Exit fullscreen mode

State Management in React

Unlike props, state is mutable and managed within the component itself. State allows components to hold and update data dynamically.

Using useState Hook in Functional Components

Modern React uses the useState Hook to handle state inside functional components.

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default Counter;
Enter fullscreen mode Exit fullscreen mode

Managing State in Class Components (Deprecated in Modern React)

For class components, state was managed using this.state and updated using this.setState():

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices for Using Components, Props, and State

  1. Keep Components Small and Focused: Each component should have a single responsibility and be easily reusable.

  2. Use Functional Components and Hooks: Prefer functional components over class components for better performance and readability.

  3. Make State Updates Immutable: Always use state updater functions when modifying state.

  4. Use Props for Read-Only Data: Do not modify props inside the child component.

  5. Lift State Up When Needed: If multiple components need access to the same state, lift it up to the nearest common ancestor.


Conclusion

Components, props, and state are fundamental concepts in React. Understanding their roles and how they interact allows developers to build powerful, maintainable applications. By following best practices, you can create clean and efficient React components that scale well.

In the next article, we’ll explore event handling and conditional rendering in React to make components more interactive.

Top comments (0)