Functional vs class components in React JS

Introduction

In this tutorial, we are going explain what a functional and class component is and then we will look into the differences between them.

Functional Components

Functional components are javascript functions. It accepts a single “props” (which stands for properties) object argument with data and returns a React element.

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

Class Components

We can also use E6 class feature to define a React component by extending React.Component

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

Difference between functional and class components

difference between functional and class components in react js

Defining state of component

This is one of the biggest and most important difference between a functional component and class component. We cannot define state of the component inside a functional component. We can only do so in the class component.

  
    class Welcome extends React.Component {
      state = {
        name: 'Techdomain'
      }
      render() {
        return <h1>Hello, {this.state.name}</h1>;
      }
    }
  

Adding state to the component is necessary when you want the component to render again when the state is changed. In the above example, we can also store the name value inside a variable in a functional component. But if the name component changes (maybe due to external api or user input), then component would not rerender.

Using references inside component

In React, we can use the refs to integrate uncontrolled componnent or 3rd party libraries. Props are the only way to pass data between component. But there are few cases where we cannot use the props, and modify the child imperatively (instead of declarative way).

Using Refs for a class component
  
    class CustomTextInput extends React.Component {
      // ...
    }    

    class AutoFocusTextInput extends React.Component {
      constructor(props) {
        super(props);
        this.textInput = React.createRef();
      }
    
      componentDidMount() {
        this.textInput.current.focusTextInput();
      }
    
      render() {
        return (
          <CustomTextInput ref={this.textInput} />
        );
      }
    }
  

Using refs for a funtional component - But the below code will not work

  
    function MyFunctionComponent() {
      return <input />;
    }
    
    class Parent extends React.Component {
      constructor(props) {
        super(props);
        this.textInput = React.createRef();
      }
      render() {
        // This will *not* work!
        return (
          <MyFunctionComponent ref={this.textInput} />
        );
      }
    }
  

Using hooks inside component

There are several problems of using classes in React. Class components do not minify well, they make hot reloading of modules flaky and unreliable.

Hooks allow use of React's features without using classes. Hooks embrace functional components. Hooks provide features of React like state, lifecycle methods inside a funtional component.

You cannot use hooks inside a class component, as class component itself provides all the features of React like state and lifecycle methods.

  
    import React, { useState } from 'react';

    function Example() {
      // Declare a new state variable, which we'll call "count"
      const [count, setCount] = useState(0);

      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
  

In the above code, we define the state count with the initial value of 0 (passed as param inside useState hook). Rest of code is similar to a functional component. Main point to note here is that, even though it is a functional component, we are able to use the React's feature of state using hooks.

Using lifecycle methods

In a class component, we can use lifecycle methods like componentDidMount, componentWillUnMount

  
    import React, { Component } from 'react';

    class Example extends Component{
      state = {
        name: ''
      }
      componentDidMount(){
        this.setState({
          name: 'Techdomain'
        })
      }
      render(){
        return <div>{this.state.name}</div>
      }
    }
  

In a functional component, it is not possible to use lifecycle methods without hooks. Just like state hook, React offers different hooks called effect hook which can be used to update the component.

  
    import React, { Component } from 'react';

    function Example(){
      const [name, setName] = useState('');

      // Similar to componentDidMount and componentDidUpdate:
      useEffect(()=>{
        setName('Techdomain');
      })
      return <div>{name}<div>;
    }
  

Conclusion

Although earlier some features of React were not available inside a functional component, now with React 16.8, you can use those features using hooks. Given the drawbacks of class components like improper minification of code and flaky hot reloading, it is now more preferable to use functional components with hooks.