Accessing the previous state in React Js

Last updated : Jul 30, 2023 12:00 AM

Sometimes we need to make decisions or calculations based on the previous state value of a state variable. For example, I want to call a particular API based on the value of the state variable color. It only takes a simple if statement.

componentDidUpdate() {
   if(this.state.color === "blue"){
      console.log("Loading blue api!!!")
   }
}

But what if I want to load the green-to-blue API when my state variable color transitions from green to blue?

To solve this problem, React Js passes the previous state and the previous props to the componentDidUpdate() function. Here is how to implement it.

componentDidUpdate(prevProps: Props, prevState: State) {
   if(prevState.color === "green" && this.state.color === "blue"){
      console.log("Loading Green to Blue!!!")
   }
}

Below is the complete class component to demonstrate how to access the previous state in React lifecycle methods.

import { Component } from "react";

interface Props {}

interface State {
   color: string
}

export default class App extends Component{

   constructor(props: Props) {
      super(props)
      this.state = {color: "white"};
      this.changeColor = this.changeColor.bind(this)
   }

  componentDidUpdate(prevProps: Props, prevState: State) {
      if(prevState.color === "green" && this.state.color === "blue"){
         console.log("Loading Green to Blue!!!")
      }
   }

   changeColor(color: string) {
      this.setState({color: color})
   }

   render(){
      return <>
         <div style={{backgroundColor: this.state.color}}>Color</div>
         <button 
            style={{backgroundColor: "red", color: "white"}}
            onClick={() => this.changeColor("red")}>
               Update to Red
            </button>
            <button 
               style={{backgroundColor: "green", color: "white"}}
               onClick={() => this.changeColor("green")}>
                  Update to Green
            </button>
            <button 
               style={{backgroundColor: "blue", color: "white"}}
               onClick={() => this.changeColor("blue")}>
                  Update to Blue
            </button>
            <button 
               style={{backgroundColor: "yellow", color: "white"}}
               onClick={() => this.changeColor("yellow")}>
                  Update to Yellow
            </button>
      </>
   }
}
Figure 1 : Previous state value in React Js
Figure 1 : Previous state value in React Js

Previous state in functional components

Unlike class components, functional components do not provide an out-of-the-box solution to access the previous value of a state variable in lifecycle hooks. Therefore, I must implement a solution to preserve the previous state value. Below is one way to do it.

const usePrevious = (color: string) => {
   const prev = useRef<string>()
   useEffect(() => {
      prev.current = color
   }, [color])
   return prev.current
}

That will return my previous state value each time I call it in each component re-render. Here is a complete example of how to use it.

import { useEffect, useRef, useState } from "react"

export const FunctionalComponent = () =>{

const [color, setColor] = useState("green")
const prevColor = usePrevious(color)

   useEffect(() => {
      if(prevColor === "green" && color === "blue"){
         console.log("Loading Green to Blue!!!")
      }
   })

   const changeColor = (color: string) => {
      setColor(color)
   }

   return(<>
      <div style={{backgroundColor: color}}>Color</div>
      <button 
         style={{backgroundColor: "red", color: "white"}}
         onClick={() => changeColor("red")}>
            Update to Red
         </button>
         <button 
            style={{backgroundColor: "green", color: "white"}}
            onClick={() => changeColor("green")}>
               Update to Green
         </button>
         <button 
            style={{backgroundColor: "blue", color: "white"}}
            onClick={() => changeColor("blue")}>
               Update to Blue
         </button>
         <button 
            style={{backgroundColor: "yellow", color: "white"}}
            onClick={() => changeColor("yellow")}>
               Update to Yellow
         </button>
   </>)
}

const usePrevious = (color: string) => {
   const prev = useRef<string>()
   useEffect(() => {
      prev.current = color
   }, [color])
   return prev.current
}
Lance

By: Lance

Hi, I'm Lance Raney, a dedicated Fullstack Developer based in Oklahoma with over 15 years of exp

Read more...