We're planting a tree for every job application! Click here to learn more

Class-Based Components vs Functional Components In React

Damilola Adedoyin Ezekiel

31 Aug 2021

•

6 min read

Class-Based Components vs Functional Components In React
  • React

In react, there are two ways to create components. Components can either be Class-based or Functional. As a newbie who just started learning React, understanding when to use either of these approaches might be a bit confusing. Although both the class-based component and the functional component give the same result depending on what you're trying to achieve, there are still some differences between these two, and in this article, we will be covering the major differences between the two components.

Differences between Class-Based Components and Functional Components

  • Rendering JSX

    One noticeable difference between the class and functional components is the syntax. The class component extends to react component which has a render method and then it returns a JSX element while the functional component is a plain javascript function that returns JSX.

Class components (without destructuring)

When writing a class component, we can either extend it to React.Component or we destructure it and extend it to the Component alone. The render() method is the only required method in a class component. Whenever the render method is called, it examines this. props and this. state and returns react elements(JSX), arrays and fragments, etc. It does not modify the component state.

import React from 'react';

class App extends React.Component {
  render() {
    return <h4>Hello World!</h4>;
  }
}

Class components (with destructuring)

Destructuring is an ES6 feature and you can learn more about it here

import React, { Component } from 'react';

class App extends Component {
  render() {
    return <h4>Hello World!</h4>;
  }
}

Functional components(using arrow functions)

Functional components can also be created using the ES6 arrow function feature. Arrow Functions are more simple and have a concise syntax for creating functions, which often makes them better to use than Function Expressions.

You can read more about it here

import React from "react";

const App = () => {
  return <h1> Hello World! </h1>;
}

Functional Component(using function Expressions)

import React from "react";

function App() {
  return <h1> Hello World! </h1>;
}
  • Passing Props

Props is short for properties and they are used as a means to communicate between the components, basically passing data from parent to child component. Passing props can be a bit confusing sometimes, let's see how props are being passed in both components.

Class-Based Component.

In a class-based component, we have to use this keyword to access the prop or we can destructure it to get our value from the prop

import React, { Component } from "react";

class ParentComponent extends Component {
  render() {
    return (
      <>
        <ChildComponent name="sarah" age="12" hobby="cycling"/>
      </>
    );
  }
}

class ChildComponent extends Component {
  render() {
    return (
      <>
        <h4>My name is {this.props.name}</h4>
        <h4>I am {this.props.age} years old</h4>
        <h4>I love {this.props.hobby}</h4>
      </>
    );
  }
}
// we can also destructure it to look like this
class ChildComponent extends Component {
  render() {
    const { name,age,hobby } = this.props
    return (
      <>
        <h4>My name is {name}</h4>
        <h4>I am {age} years old</h4>
        <h4>I love {hobby}</h4>
      </>
    );
  }
}

Functional Component

In a functional component, the prop is being passed directly as an argument to the function and we can now access the prop by using prop.value.

P.S: The value could be anything.

import React from "react";

const ParentComponent = () => {
  return <ChildComponent name="sarah" age="12" hobby="cycling" />;
};

const ChildComponent = (props) => {
  return (
    <>
      <h4>My name is {props.name}</h4>
      <h4>I am {props.age} years old</h4>
      <h4>I love {props.hobby}</h4>
    </>
  );
};

// with destructuring
const ChildComponent = (props) => {
  const {name,age,hobby} = props
  return (
    <>
      <h4>My name is {name}</h4>
      <h4>I am {age} years old</h4>
      <h4>I love {hobby}</h4>
    </>
  );
};
  • Handling and Updating State.

Before the release of React 16.8, handling and updating the state was only possible using a class-based component. But now, we can also handle state in functional components using the React hooks useState.

To understand how state works in react, we will build a counter application that increments and decrements whenever we have a call to action. This counter app will show us how to handle and update state in both class and functional components.

Class-Based Component

In the class-based component, we can access the value of the state by using this.state inside JSX . You should not update the state directly instead you're to use setState to update the value of the state.

//this is wrong

this.state.name = " Hannah"

//do this instead

 this.setState({ name: "Hannah" });

import React, { Component } from "react";

class App extends Component {
  state = {
    count: 0
  };
  addCount = () => {
    this.setState({ count: this.state.count + 1 });
  };
  minusCount = () => {
    if (this.state.count <= 0) {
      this.setState({ count: this.state.count });
    } else {
      this.setState({ count: this.state.count - 1 });
    }
  };
  render() {
    return (
      <div>
        <button onClick={this.minusCount}>-</button>
        <p>{this.state.count}</p>
        <button onClick={this.addCount}>+</button>
      </div>
    );
  }
}

Functional Component

We use useState to handle state in functional components. The useState hook gives us an array to work with and this array is made of two values: the state and the setter function and this setter function is what we use to update our state. The useState hook also takes in a value of what the default state is.

import React, { useState } from "react";

function App() {
  const [count, setCount] = useState(0);
  const addCount = () => {
      setCount( count + 1 );
  };
  const minusCount = () => {
    if (count <= 0) {
      setCount(count);
    } else {
      setCount( count - 1 );
    }
  };

  return (
    <div className="App">
      <button onClick={minusCount}>-</button>
      <div>{count}</div>
      <button onClick={addCount}>+</button>
   </div>
  );
};

In the example above, count is our current state while setCount is the setter function that updates our state. We then passed an onClick event to our button and it takes in a function that is minusCount. The setter function which is setCount is now used to decrement the value of our state inside the minusCount function.

Note

The conditional statement in the minusCount function helps to stop the counter from counting negatively.

It is advisable to use functional components if your component will be a stateless one that is a component that does not have state.

  • Lifecycle Methods

Lifecycle methods are special methods built-in to React, used to operate on components throughout their duration in the DOM. For example, when the component mounts, renders, updates, or unmounts.

Class-based Component

In the class-based component, there are four main types of lifecycle methods. These are:

  • Render: we already know the render method is the most important lifecycle method. Every class component needs to contain a render method.

  • componentDidMount: it is called when an instance of a component is being created or inserted into the DOM. This is usually where we call our APIs, set timers, and also add event listeners.

  • componentDidUpdate: This is called when a component is being re-rendered as a result of changes to either its props or state. It runs when our component is being updated.

  • componentWillUnmount: This is called when a component is being removed from the DOM.

import React, { Component } from "react";

class Header extends Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "yellow"})
    }, 1000)
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

Functional Component

useEffect lets you perform side effects in a function. Since we've already gone through React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

This is the useEffect syntax :

useEffect ( () => {}, [] )

In the curly brackets, you can write the code that will be executed. The useEffect hook takes a second parameter, a “dependencies” array, that will only re-run the effect when the values within the array change across re-renders. This allows us to optimize how many times the effect is run. Although the dependency array at the end of the hook is optional however it will be needed more often.

There are three ways to express the dependency array :

a. With an empty array added at the end of the hook.

useEffect ( () => {
  //do something here
}, [])

This works exactly like thecomponentDidMount and this means that the hook will be run as soon as the component is inserted into the DOM.

b. Add the dependency array with a value.

This is quite similar to the example above, just that in this case a value is placed into the array and what this means is the hook will only be re-rendered as soon as the value changes. This is equal to how componentDidUpdate works.

useEffect ( () => {
  //do something here
}, [value])

c. Without adding the dependency array.

You can also completely leave out the dependency array. This way, the useEffect hook runs anytime the component is updated and right after the initial render. This is the difference compared to the componentDidUpdate lifecycle method because it also runs after the initial render. This way it would be equal to a componentDidMount and componentDidUpdate method combined.

The return statement we are adding to our useEffect is actually equal to a componentWillUnmount method.

useEffect(() => {
  const timer = setTimeout(() => {
    // do something here
  }, 2000)
  return () => {
    // Cleanup work goes in here
    clearTimeout(timer)
  }
})

If you write a return statement like the above in a useEffect, it will do the same as a componentWillUnmount method. As you can see, there is a lot to the useEffect hook. You can also create your own custom hooks with it.

Summary

Using either of class-based or function approach comes with its own pros and cons however, I want you to take note of the following:

Functional components are easy to write and it also makes our code cleaner and more readable whereas the this keyword in-class component can be confusing most times. However, this is not a debate to choose one over another. The majority of React codebases are still heavily dependent on the Class component and React has said that it will not stop supporting class components in the next foreseeable future. But it is advisable to start embracing functional components as hooks are taking over modern React.

Did you like this article?

Damilola Adedoyin Ezekiel

Developer Advocate and Technical Writer

See other articles by Damilola

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub