Blog

You are here: Blog / Difference between Functional Components and Class Components in React


  • Difference between Functional Components and Class Components in React

    Here we covered functionality we use for both functional components and class components and based on that we see the difference between functional and class component through the code.


    Functional Components:

    Functional component is a JavaScript function which accepts props as an argument and returns a React element.

    Functional components don't use the render() method to return HTML. Below is sample code for how to write the functional component.

    import React from 'react';
    
    const Demo = () => {
        return <h1>Hello world!</h1>;
    }
    
    export default Demo;
    

    Functional components are also known as Stateless components .

    For storing data it is used useState() hooks

    import React, { useState } from 'react';
    
    const Demo = () => {
        const [title, setTitle] = useState('Hello world!');
    
        return <h1>{title}</h1>;
    }
    
    export default Demo;

    If we want to render some data at component render or component update or new props arrived time then useEffect() hooks are used in functional components.

    import React, { useState } from 'react';
    
    const Demo = () => {
        const [title, setTitle] = useState('Before render component');
    
        useEffect(() => {
            setTitle('After render component')
        });
    
        return <h1>{title}</h1>;
    }
    
    export default Demo;
    

    Following are the list of react hooks which we can use in functional base component
    • useState
    • useEffect
    • useContext
    • useReducer
    • useCallback
    • useMemo
    • useRef

    useState & useEffect:

    import React, { useState } from 'react';
    
    const Demo = () => {
        const [title, setTitle] = useState('Before render component');
    
        useEffect(() => {
        setTitle('After render component')
        });
    
        return <h1>{title}</h1>;
    }
    
    export default Demo;
    


    useContext:

    import React from 'react';
    
    export const UserContext = React.createContext();
    
    function Test() {
        return (
            <div>
                <UserContext.Provider value={'Result'}>
                    <Demo />
                </UserContext.Provider>
            </div>
        )
    }
    

    to usecontext need to add useHooks which is as below

    import React, { useContext } from 'react';
    import { UserContext, UserContext } from './test';
    
    const UseHooks = () => {
        const user = useContext(UserContext);
        return <h1>{user}</h1>;
    }
    
    export default UseHooks;
    


    useReducer:

    import React, { useReducer } from 'react';
    
    const initialState = 0;
    
    const reducer = (state, action) => {
        if (action.type === 'INCREMENT') {
        return state + 1;
        } else if (action.type === 'DECREMENT') {
        return state - 1;
        }
        return state;
    }
    
    const Demo = () => {
        const [state, dispatch] = useReducer(reducer, initialState);
    
        return (
        <>
                <div>{state}</div>
                <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
                <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
            </>
        )
    }
    
    export default Demo;


    useCallback:
    • useCallback will remember the function
    • useCallback will remember the function that we provide it in below example (value) => { setName(value); }

    import React, { useCallback, useState } from 'react';
    
    const Demo = () => {
        const [name, setName] = useState('');
    
        const buttonClick = useCallback((value) => {
        setName(value);
        },[name] )
    
        return (
        <>
            <div>{name}</div>
            <button onClick={() => buttonClick('UseCallback')}>Click me</button>
            </>
        );
    }
    
    export default Demo;
    


    useMemo:
    • useMemo will remember the value that is returned.
    • useMemo will remember the result of the function that we provide it with until the dependencies (name) have changed.

    import React, { useState, useMemo } from 'react';
    
    const Demo = () => {
        const [name, setName] = useState('');
    
        const buttonClick = useMemo((value) => {
        setName(value);
                                         },[name] )
    
        return (
        <>
            <div>{name}</div>
            <button onClick={() => buttonClick('UseMemo')}>Click me</button>
            </>
        );
    }
    export default Demo;
    


    useRef:

    import React, { useRef } from 'react';
    
    const Demo = () => {
        const inputEle = useRef(null);
        const onButtonClick = () => {
            inputEle.current.focus();
        };
        return (
        <>
                <input ref={inputEle} type="text" />
                <button onClick={onButtonClick}>Focus the input</button>
            </>
        );
    }
    
    export default Demo;
    


    Class Components:

    • Class component is required to import from react.
    • It must have the render() method to returning HTML.

      import React, { Component } from 'react';
      
      class Demo extends Component {
          render() { 
              return ( 
                  <div>Hello world!</div>
              );
          }
      }
       
      export default Demo;

    • Class components are also known as Stateful components. Because we are using state object to store data.

      import React, { Component } from 'react';
      
      class Demo extends Component {
          constructor(props) {
          super(props);
          this.state = { title: 'Hello world!' };
          }
            
          render() { 
          return ( 
          <div>{this.state.title}</div>
          );
          }
      }
       
      export default Demo;
      

    • If we want to rendering some data at component render time then componentDidMount() lifecycle method is used in class component.
    • If we want to rendering some data when new props is arrived then getDerivedStateFromProps() lifecycle method is used in class component.

      import React, { Component } from 'react';
      
      class Demo extends Component {
          constructor(props) {
              super(props);
              this.state = { title: '' };
          }
      
          componentDidMount() {
              this.setState({ title: 'After component rendering' })
          }
      
          render() {
              return (
                  <div>{this.state.title}</div>
              );
          }
      }
      
      export default Demo;
      
      import React, { Component } from 'react';
      
      class Demo extends Component {
          constructor(props) {
              super(props);
              this.state = { title: '' };
          }
      
          static getDerivedStateFromProps(nextProps, prevState){
              let update = {};
              update.title = nextProps.title;
              return Object.keys(update).length === 0 ? null : update;
          }
      
          render() {
              return (
                  <div>{this.state.title}</div>
              );
          }
      }
      
      export default Demo;
      

    List of react lifecycle methods
    • componentDidMount()
    • componentDidUpdate()
    • componentWillMount()
    • componentWillUnmount()
    • getDerivedStateFromProps()
    • componentDidCatch()
    • UNSAFE_componentWillReceiveProps() etc

    componentDidMount():

    import React, { Component } from 'react';
    
    class Demo extends Component {
        constructor(props) {
        super(props);
        this.state = { title: '' };
        }
    
        componentDidMount() {
        this.setState({ title: 'After component rendering' })
        }
    
        render() {
        return (
        <div>{this.state.title}</div>
        );
        }
    }
    
    export default Demo;
    


    componentDidUpdate():

    import React, { Component } from 'react';
    
    class Demo extends Component {
        constructor(props) {
            super(props);
        }
    
        componentDidUpdate(){
            if(document.getElementById('inputFocus')){
                document.getElementById('inputFocus').focus();
            }
        }
    
        render() {
            return (
                <div>
                    <input
                        type ='text'
                        id='inputFocus'
                    />
                </div>
            );
        }
    }
    
    export default Demo;
    


    componentWillMount() && componentWillUnmount():

    import React, { Component } from 'react';
    
    class Demo extends Component {
        constructor(props) {
            super(props);
            this.state = { mounted: false };
        }
    
        componentWillMount() {
            this.setState({ mounted: true });
        }
    
        componentWillUnmount() {
            this.setState({ mounted: false });
        }
    
        render() {
            return (
                <div>{this.state.title}</div>
            );
        }
    }
    
    export default Demo;


    getDerivedStateFromProps():

    import React, { Component } from 'react';
    
    class Demo extends Component {
        constructor(props) {
            super(props);
            this.state = { title: '' };
        }
    
        static getDerivedStateFromProps(nextProps, prevState){
            let update = {};
            update.title = nextProps.title;
            return Object.keys(update).length === 0 ? null : update;
        }
    
        render() {
            return (
                <div>{this.state.title}</div>
            );
        }
    }
    
    export default Demo;
    


    componentDidCatch():

    import React, { Component } from 'react';
    
    class Demo extends Component {
        constructor(props) {
            super(props);
            this.state = {
                error: null,
                errorInfo: null
            };
        }
    
        componentDidCatch(error, errorInfo) {
            this.setState({
                error: error,
                errorInfo: errorInfo
            });
        }
    
        render() {
            return (
                <div>
                </div>
            );
        }
    }
    
    export default Demo;


    UNSAFE_componentWillReceiveProps():

    import React, { Component } from 'react';
    
    class Demo extends Component {
        constructor(props) {
            super(props);
            this.state = { title: '' };
        }
    
        UNSAFE_componentWillReceiveProps(nextProps) {
            this.setState({title: nextProps.title});
        }
    
        render() {
            return (
                <div>{this.state.title}</div>
            );
        }
    }
    
    export default Demo;
    

    Conclusion

    As we can see the code for both functional base and class base component and we noticed that functional base component is more simple and shorter compared to class base component. React team supporting more reacts hooks in functional base component compare to class base component. Also react team mention on there 14.0 release that they will create performance optimizer in functional components.