Skip to content

ReactJS

What is a Function Component in React?

A Function Component is the standard way to create components in modern React. It's essentially a JavaScript function that accepts an object of properties, called props, and returns JSX to describe what the UI should look like.

Think of it as a simple template: you pass data in (props), and it returns a piece of the user interface.

A Simple Example

Here's a basic Welcome component. It takes a name prop and displays a greeting. It can be written as a regular function or, more commonly, as an arrow function.

Regular Function Syntax:

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

Arrow Function Syntax (very common):

JavaScript
const Welcome = (props) => {
  return <h1>Hello, {props.name}!</h1>;
};

// Or even more concisely:
const Welcome = ({ name }) => <h1>Hello, {name}!</h1>;

In this example, props is an object like { name: 'Sarah' }, and {props.name} accesses its value.

Key Characteristics

  • Simplicity: They are just JavaScript functions, which makes them easier to read, write, and test than the older class components. There's no need to worry about the this keyword.

  • Hooks: Originally, function components were "stateless." Now, with the introduction of Hooks (like useState and useEffect), they can manage their own state, handle side effects, and do everything a class component can, but with a simpler syntax.

  • The Modern Standard: Function components with Hooks are the recommended way to build new applications in React. They lead to cleaner, more reusable, and more maintainable code.

What is Class Component in React?

Class components are the original way of creating stateful, dynamic components in React. They are JavaScript ES6 classes that extend the React.Component base class and must include a render() method to return the component's UI.

While modern React development prefers function components with Hooks, you'll still find class components in older codebases, so it's important to understand them.

Core Features of a Class Component

  • render() Method: This is the only required method in a class component. It's where you define the JSX that will be displayed on the screen.
  • Props: Data passed from a parent component is available through this.props.
  • State: Class components have built-in state management.
  • State is initialized in the constructor as an object called this.state.
  • It's updated using the special method this.setState(). Calling this.setState() tells React to re-render the component with the new state data.
  • Lifecycle Methods: These are special methods you can define to run code at specific times in a component's life, such as when it first mounts to the DOM (componentDidMount) or just before it's removed (componentWillUnmount).

Simple Example: A Counter

Here’s a basic counter that shows how state and setState work in a class component.

JavaScript
import React from "react";

class Counter extends React.Component {
  // 1. Initialize state in the constructor
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  // A method to update the state
  incrementCount = () => {
    // 2. Use this.setState to update the state
    this.setState({ count: this.state.count + 1 });
  };

  // 3. The render method returns the UI
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={this.incrementCount}>Click me</button>
      </div>
    );
  }
}

export default Counter;

Class vs. Function Components: The Modern View

Today, function components with Hooks are the standard. They accomplish the same things as class components but with less code, no confusing this keyword, and a more straightforward way to handle logic. Class components are now considered the "legacy" way of writing React.

Syntax and Structure

The most immediate difference is how they are written. A function component is a plain JavaScript function, whereas a class component is an ES6 class that extends React.Component.

  • Function Component: A simple function that accepts props as an argument and returns JSX.
JavaScript
import React from "react";

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
  • Class Component: A class with a render() method that returns JSX. Props are accessed via this.props.
JavaScript
import React from "react";

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

State Management

How components handle internal data, or "state," is a fundamental difference.

  • Function Component: Uses the useState Hook to manage state. This Hook returns the current state value and a function to update it. There is no this keyword involved.
JavaScript
import React, { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0); // Using the useState Hook
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
  • Class Component: Uses the this.state object to hold state. State is updated using the this.setState() method, which requires binding the this context in older class patterns.
JavaScript
import React from "react";

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

  render() {
    return (
      <button onClick={() => this.setState({ count: this.state.count + 1 })}>
        {this.state.count}
      </button>
    );
  }
}

Lifecycle Methods

Lifecycle methods are special methods that run at different stages of a component's life (e.g., when it's first created, updated, or removed).

  • Function Component: Uses the useEffect Hook to handle side effects, effectively covering the jobs of multiple class lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount all in one API.
JavaScript
import React, { useState, useEffect } from "react";

function MyComponent() {
  useEffect(() => {
    // Runs after the component mounts
    console.log("Component did mount");

    return () => {
      // Runs when the component unmounts
      console.log("Component will unmount");
    };
  }, []); // Empty array means it runs only once (on mount)
}
  • Class Component: Relies on specific, named lifecycle methods that you override in the class definition.
JavaScript
import React from "react";

class MyComponent extends React.Component {
  componentDidMount() {
    console.log("Component did mount");
  }

  componentWillUnmount() {
    console.log("Component will unmount");
  }

  render() {
    return <div>Check the console!</div>;
  }
}

Summary: Key Differences

Feature Function Component (with Hooks) Class Component
Syntax Simple JavaScript function ES6 class extending React.Component
State Managed with the useState() Hook Managed with this.state and this.setState()
Lifecycle Handled with the useEffect() Hook Uses methods like componentDidMount() etc.
this Keyword Not used; props are direct arguments Used extensively for props, state, and methods
Code Verbosity Generally less code, more concise More boilerplate and ceremonious code
Modern Practice Recommended and standard for new React apps Considered legacy; less common in modern codebases

What are props in React?

React props (short for "properties") are used to pass data from a parent component down to a child component. They are the primary way to make your components reusable and dynamic. 🎁

Think of them as arguments you pass to a JavaScript function. The parent component provides the props, and the child component receives and uses them.


An Analogy: Customizing a Button

Imagine you have a generic Button component. You want to reuse this button all over your app, but with different text and colors. Instead of creating a new component for each variation, you can pass its configuration as props.

JavaScript
// You can customize the 'Button' component with props
<Button text="Sign Up" color="blue" />
<Button text="Delete" color="red" />
<Button text="Cancel" color="gray" />

Here, text and color are props that tell the Button component how to render itself.


How Props Work in Code

Data flows in one direction: from parent to child.

  1. The Parent Component (App) passes the props. The parent defines the data and passes it as attributes in the JSX tag, just like HTML attributes.

    JavaScript
    import React from 'react';
    import UserProfile from './UserProfile';
    
    function App() {
      return (
        <div>
          {/* We are passing 'name' and 'age' as props */}
          <UserProfile name="Alice" age={30} />
          <UserProfile name="Bob" age={25} />
        </div>
      );
    }
    
    export default App;
    
  2. The Child Component (UserProfile) receives the props. The child function component receives a single argument: an object containing all the props.

    JavaScript
    import React from 'react';
    
    // The 'props' object contains all the data passed from the parent
    function UserProfile(props) {
      // Access the data using dot notation
      return (
        <p>
          My name is {props.name} and I am {props.age} years old.
        </p>
      );
    }
    
    // You can also destructure props directly for cleaner code
    // function UserProfile({ name, age }) {
    //   return <p>My name is {name} and I am {age} years old.</p>;
    // }
    
    export default UserProfile;
    

Key Rules of Props

  • Props are Read-Only: This is a fundamental rule in React. A component must never modify the props it receives. They are immutable. This ensures a predictable, unidirectional data flow, making your app easier to debug.

  • Anything Can Be a Prop: You can pass any JavaScript data type as a prop, including strings, numbers, arrays, objects, and even functions. Passing functions is a common way for a child component to communicate back to its parent (e.g., sending an onClick event).

What are React Hooks?

React Hooks are special functions that let you use state and other React features in function components, which were previously only available in class components. They allow you to write simpler, cleaner, and more organized code without needing to write a class.

All Hooks begin with the word use (e.g., useState, useEffect).

Why Were Hooks Introduced?

Before Hooks, if you needed to manage state (data that changes over time) or use lifecycle methods (like running code when a component is first added to the screen), you had to convert your simple function component into a more complex class component.

Classes in JavaScript can be confusing, especially with the this keyword and binding methods. Hooks solve this by letting you "hook into" React's powerful features right from a simple function.

The Most Common Hooks

While there are several built-in Hooks, two are used in almost every React application.

useState

This is the most fundamental Hook. It lets you add a state variable to your component.

  • What it does: It declares a "state variable" and returns a pair: the current state value and a function that lets you update it.

  • Analogy: Think of a light switch. useState gives you the current status of the light (on or off) and the switch itself to change that status.

Here’s a simple counter example:

JavaScript
import React, { useState } from "react";

function Counter() {
  // Declares a state variable named 'count' initialized to 0
  // 'setCount' is the function to update 'count'
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      {/* When clicked, call setCount to update the state */}
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

useEffect

This Hook lets you perform side effects in your components. Side effects are actions that interact with the "outside world", such as:

  • Fetching data from an API
  • Setting up a subscription

Manually changing the DOM

  • What it does: It runs a function after React has updated the DOM. By default, it runs after every render, but you can configure it to run only when specific values change.

  • Analogy: useEffect is like setting a reminder to do something after a specific event happens, like after a component appears on the screen or after a piece of state changes.

Here’s an example that updates the document title:

JavaScript
import React, { useState, useEffect } from "react";

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

  // This side effect runs after every render
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  }); // No dependency array, so it runs on every update

  return (
    <div>
      <p>Check the browser tab title!</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

The Rules of Hooks

React relies on the call order of Hooks to work correctly. To ensure this, you must follow two simple rules:

  • Only Call Hooks at the Top Level: Don't call Hooks inside loops, conditions, or nested functions. Always use them at the top level of your React function.

  • Only Call Hooks from React Functions: Call them from React function components or from custom Hooks, not from regular JavaScript functions.