Back to Course

Learn React

0% Complete
0/0 Steps
Lesson 4 of 32
In Progress

Creating Functional and Class-Based Components

In React, a component is a piece of code that represents a part of a UI. Components can be either functional or class-based, and they can be either stateful or stateless. In this article, we’ll take a closer look at how to create functional and class-based components in React.

Functional components

Functional components, also known as stateless or dumb components, are simply JavaScript functions that take in props (short for properties) and return a JSX element. They are called functional because they do not have their own state and are purely responsible for rendering the UI based on the props that are passed to them.

Here’s an example of a functional component:

import React from 'react';

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

In this example, the Welcome component is a functional component that takes in a name prop and returns a JSX element that displays a greeting with the name.

Functional components are simple and easy to understand, and they are often used for presentational components that only need to render the UI and do not need to manage any state.

Class-based components

Class-based components, also known as stateful or smart components, are JavaScript classes that extend the React.Component class and define a render() method. They are called class-based because they are defined using a class, and they can have their own state and lifecycle methods.

Here’s an example of a class-based component:

import React from 'react';

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

In this example, the Welcome component is a class-based component that has a render() method that returns a JSX element that displays a greeting with the name prop.

Class-based components are more powerful and flexible than functional components, and they are often used for container components that need to manage state and handle interactions.

Creating a functional component

To create a functional component, you simply define a function that takes in props and returns a JSX element. The function can be as simple or as complex as you need it to be, and it can include other components as well.

Here’s an example of a simple functional component:

import React from 'react';

function Hello() {
  return <h1>Hello, world!</h1>;
}

And here’s an example of a more complex functional component that includes other components:

import React from 'react';

function Welcome(props) {
  return (
    <div>
      <h1>Welcome, {props.name}</h1>
      <p>This is your dashboard.</p>
      <Button label="Logout" onClick={props.onLogout} />
    </div>
  );
}

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

In this example, the Welcome component is a functional component that takes in a name and onLogout prop and returns a JSX element that includes a heading, a paragraph, and a Button component. The Button component is a functional component that takes in a label and onClick prop and returns a JSX element that is a button with the given label and onClick handler.

Creating a class-based component

Class-based components, also known as stateful or smart components, are JavaScript classes that extend the React.Component class and define a render() method. They are called class-based because they are defined using a class, and they can have their own state and lifecycle methods.

To create a class-based component, you define a class that extends the React.Component class and define a render() method. The class can have its own state and lifecycle methods, and it can include other components as well.

Here’s an example of a simple class-based component:

import React from 'react';

class Hello extends React.Component {
  render() {
    return <h1>Hello, world!</h1>;
  }
}

And here’s an example of a more complex class-based component that includes other components and manages its own state:

import React from 'react';

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: props.name,
      loggedIn: false
    };
  }

  handleLogout() {
    this.setState({ loggedIn: false });
  }

  render() {
    if (!this.state.loggedIn) {
      return <Login />;
    }
    return (
      <div>
        <h1>Welcome, {this.state.name}</h1>
        <p>This is your dashboard.</p>
        <button onClick={this.handleLogout}>Logout</button>
      </div>
    );
  }
}

function Login() {
  return (
    <form>
      <label htmlFor="email">Email:</label>
      <input type="email" id="email" />
      <br />
      <label htmlFor="password">Password:</label>
      <input type="password" id="password" />
      <br />
      <button type="submit">Log in</button>
    </form>
  );
}

In this example, the Welcome component is a class-based component that manages its own state and includes a Login component. The Welcome component has a constructor that sets its initial state based on the name prop that is passed to it. It also has a handleLogout() method that updates the loggedIn state to false. The render() method then checks the loggedIn state, and if the user is not logged in, it renders the Login component. If the user is logged in, it renders a greeting and a logout button.

The Login component is a functional component that returns a form with email and password inputs and a log in button.

Conclusion

In this article, we’ve learned about functional and class-based components in React and how to create them. Understanding the difference between functional and class-based components is essential to building applications with React, and it is an important step towards mastering the framework.

Functional components are simple and easy to understand, and they are often used for presentational components that only need to render the UI and do not need to manage any state.

Class-based components, on the other hand, are more powerful and flexible than functional components, and they are often used for container components that need to manage state and handle interactions.

To create a functional component, you simply define a function that takes in props and returns a JSX element. The function can be as simple or as complex as you need it to be, and it can include other components as well.

To create a class-based component, you define a class that extends the React.Component class and define a render() method. The class can have its own state and lifecycle methods, and it can include other components as well.

By understanding how to create functional and class-based components in React, you will be well on your way to building scalable and maintainable applications with the framework.

Exercises

To review these concepts, we will go through a series of exercises designed to test your understanding and apply what you have learned.

How do you create a class-based component in React?

To create a class-based component in React, you define a class that extends the React.Component class and define a render() method. The class can have its own state and lifecycle methods, and it can include other components as well.

For example:

import React from 'react';

class Hello extends React.Component {
  render() {
    return <h1>Hello, world!</h1>;
  }
}

What is the constructor() method in a class-based component?

The constructor() method is a special method in a class-based component that is called when the component is initialized. It is used to set the initial state of the component and bind any methods to the component instance. The constructor() method should always call the super() method with the props as its argument.

For example:

import React from 'react';

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: props.name,
      loggedIn: false
    };
    this.handleLogout = this.handleLogout.bind(this);
  }

  handleLogout() {
    this.setState({ loggedIn: false });
  }

  render() {
    if (!this.state.loggedIn) {
      return <Login />;
    }
    return (
      <div>
        <h1>Welcome, {this.state.name}</h1>
        <p>This is your dashboard.</p>
        <button onClick={this.handleLogout}>Logout</button>
      </div>
    );
  }
}

In this example, the Welcome component has a constructor() method that sets the initial state based on the name prop that is passed to it. It also binds the handleLogout() method to the component instance. The handleLogout() method updates the loggedIn state to false when it is called.

Write a React component that displays a list of items. The component should accept an array of strings as a prop and render each string as a list item.

import React from 'react';

function List(props) {
  const items = props.items.map((item, index) => {
    return <li key={index}>{item}</li>;
  });

  return (
    <ul>
      {items}
    </ul>
  );
}

export default List;

Write a React component that displays a form with two inputs: a name and an email address. The component should also have a submit button that logs the values of the inputs to the console when clicked.

import React, { useState } from 'react';

function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  function handleSubmit(event) {
    event.preventDefault();
    console.log(name, email);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" value={name} onChange={event => setName(event.target.value)} />
      </label>
      <br />
      <label>
        Email:
        <input type="text" value={email} onChange={event => setEmail(event.target.value)} />
      </label>
      <br />
      <button type="submit">Submit</button>
    </form>
  );
}

export default Form;

Write a React component that displays a loading spinner while data is being fetched from an API, and displays an error message if the API call fails.

import React, { useState, useEffect } from 'react';

function Loader() {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com');
        const json = await response.json();
        setData(json);
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    }

    fetchData();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return <div>Data: {data}</div>;
}

export default Loader;