Support People In Ukraine
Ukraine was invaded by Russia in the early morning of 24.02.2022, explosions thundered in Ukrainian cities, many civilians died, tens of millions are affected. Our army protects all Europe from the occupiers and it needs help now to restrain one of the biggest armies in the world. Please, donate a small amount.
I Am
Volodymyr Hudyma
<FrontEndDeveloper />
You Are Here: Home/React Hooks: usePrevious

React Hooks: usePrevious

July 27, 2021

Table Of Contents

    Retrieving the previous state of the component is a must in some special cases.

    While class-based components provide an easy and convenient way to do this via the componentDidUpdate() lifecycle hook, function components do not and you need to write custom logic to handle this.

    This custom logic can be extracted into a custom reusable hook, let's call it usePrevious(), which might even end up in one of the next React versions, as mentioned in the official React documentation.

    Class-Based Component: componentDidUpdate()

    First, let's see how we can get the previous state of the class-based component:

    import React, { Component } from "react";
    
    class Counter extends Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0,
          prevCount: undefined,
        };
      }
    
      handleClick = () => {
        this.setState((prevState) => ({
          count: prevState.count + 1,
        }));
      };
    
      componentDidUpdate(_prevProps, prevState) {
        // We have access to the previous state via this "prevState"
        if (prevState.count !== this.state.count) {
          this.setState({
            prevCount: prevState.count,
          });
        }
      }
    
      render() {
        return (
          <div>
            Current count: {this.state.count}, Previous count:{" "}
            {this.state.prevCount}
            <button onClick={this.handleClick}>Increment</button>
          </div>
        );
      }
    }
    
    export default Counter;

    The code is pretty simple, but long, so here is the part we are most interested in:

    componentDidUpdate(_prevProps, prevState) {
      // We have access to the previous state via this "prevState"
      if (prevState.count !== this.state.count) {
        this.setState({
          prevCount: prevState.count,
        });
      }
    };

    We use componentDidUpdate() lifecycle hook, which accepts the following arguments in the following order:

    • prevProps - an object containing previous values of props
    • prevState - an object containing previous values of state
    • snapshot - a value returned by the getSnapshotBeforeUpdate() lifecycle method if exists, otherwise undefined

    Functional Component: usePrevious()

    Functional components implement hooks instead of lifecycle methods, so which hook allows us to get the previous state?

    The answer is - at this point, there is no built-in hook for this purpose.

    But we can create our own using useRef().

    Create a new file named usePrevious.jsx with the following content:

    import { useRef, useEffect } from "react";
    
    const usePrevious = value => {
     const ref = useRef();
      
     useEffect(() => {
       ref.current = value;
     });
      
     return ref.current;
    };
    
    export default usePrevious;

    Use it then in the functional component:

    import React, { useState } from "react";
    
    import usePrevious from "./usePrevious";
    
    const Counter = () => {
      const [count, setCount] = useState(0);
      const prevCount = usePrevious(count);
      
      const handleClick = () => {
        setCount(count => count + 1);
      };
    
      return (
        <div>
          Current count: {count}, Previous count: {prevCount}
          <button onClick={handleClick}>Increment</button>
        </div>
      );
    };
    
    export default Counter;

    Note that we need to explicitly pass a value we want to observe to the custom hook.

    usePrevious() With TypeScript

    Most React applications use TypeScript, so let's add some typings to our custom hook:

    import { useRef, useEffect } from "react";
    
    const usePrevious = <T>(value: T): T | undefined => {
     const ref = useRef<T>();
      
     useEffect(() => {
       ref.current = value;
     });
      
     return ref.current;
    };
    
    export default usePrevious;

    Summary

    In this article, we learned how to get the previous state of the functional component in React.

    For this purpose, we created custom usePrevious() hook, based on the built-in useRef().

    Be sure to copy the custom hook and save it for later use, as it will certainly be needed.

    Newsletter
    Receive all new posts directly to your e-mail
    No spam, only quality content twice a week
    Let me know what you think about this article
    Click here to write response...