ReactJS

 

Exploring ReactJS usePrevious Hook: Accessing Previous State and Prop Values

  1. Introduction

ReactJS is a popular JavaScript library for building user interfaces. When working with React components, it’s often necessary to track changes in state or props. While React provides the useState hook to manage state, it doesn’t offer a built-in solution to access the previous value of a state or prop. In this blog, we’ll explore the usePrevious custom hook, which allows us to conveniently access the previous value of a state or prop in ReactJS applications.

Exploring ReactJS usePrevious Hook: Accessing Previous State and Prop Values

1.1 Overview of ReactJS

ReactJS is a declarative, component-based JavaScript library developed by Facebook. It provides an efficient way to build interactive user interfaces by breaking down the UI into reusable components. React handles the rendering of components efficiently by updating only the necessary parts of the UI when the underlying data changes.

1.1 Importance of tracking previous values in ReactJS

Tracking previous values of state or props is essential in many scenarios. For instance, you may need to compare the current and previous values to detect changes and trigger specific actions accordingly. This is particularly useful when you want to perform side effects or conditionally update the UI based on state or prop changes. Unfortunately, React doesn’t provide a built-in mechanism to access the previous value out of the box.

  1. Using useState Hook

The useState hook is one of the most commonly used hooks in React. It allows us to add state to functional components. Let’s see how it works and its limitations when it comes to tracking previous values.

2.1 Basics of useState Hook

The useState hook is imported from the ‘react’ package and can be used within functional components. It takes an initial state value as a parameter and returns an array containing the current state value and a function to update that state.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

2.2 Limitations of useState Hook for tracking previous values

Although the useState hook is powerful for managing state in React components, it doesn’t provide a built-in way to access the previous value of a state. It only gives us the current state value and a function to update it. This limitation becomes apparent when we need to compare the previous and current values of a state variable.

  1. Implementing usePrevious Hook

The usePrevious hook is a custom hook that allows us to track the previous value of a state or prop. By creating this custom hook, we can overcome the limitation of the useState hook and access the previous value whenever needed. Let’s explore how we can implement the usePrevious hook.

3.1 Understanding the concept of custom hooks

Custom hooks are JavaScript functions that utilize built-in hooks or other custom hooks to provide additional functionality to React components. They follow a naming convention of starting with the word “use” to indicate that they are hooks. Custom hooks allow us to encapsulate reusable logic and share it between components.

3.2 Creating the usePrevious hook

To create the usePrevious hook, we’ll start by importing the useRef hook from the ‘react’ package. The useRef hook allows us to create a mutable value that persists across re-renders without triggering a re-render itself.

Here’s an example implementation of the usePrevious hook:

import { useRef, useEffect } from 'react';

function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

In this code, we define the usePrevious function that takes a value as a parameter. We create a ref variable using the useRef hook and assign it to the ref constant. Then, we use the useEffect hook to update the ref.current value whenever the input value changes. By including [value] as the dependency array, we ensure that the effect is triggered only when the value changes. Finally, we return the ref.current value, which represents the previous value.

3.3 Usage example of the usePrevious hook

Now that we have implemented the usePrevious hook, let’s see how we can use it in a component.

import React from 'react';
import { usePrevious } from './usePrevious';

function Counter() {
  const [count, setCount] = useState(0);
  const previousCount = usePrevious(count);

  useEffect(() => {
    console.log('Previous count:', previousCount);
  }, [previousCount]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

In this example, we import the usePrevious hook from the ‘./usePrevious’ file (assuming it’s in the same directory). We declare a state variable called count using the useState hook. We then call the usePrevious hook, passing in the count variable, and store the result in the previousCount variable.

Inside the useEffect hook, we log the previousCount value whenever it changes. This demonstrates how we can access the previous value of the count state using the usePrevious hook.

  1. Code Samples

In this section, we’ll provide additional code samples to illustrate the use of useState for tracking previous state and the implementation of the usePrevious hook.

4.1 useState example: Tracking previous state

Let’s say we have a form with an input field that updates a state variable called inputValue. We want to track the previous value of the inputValue and perform some actions based on its change.

import React, { useState, useEffect } from 'react';

function Form() {
  const [inputValue, setInputValue] = useState('');
  const [previousValue, setPreviousValue] = useState('');

  useEffect(() => {
    if (inputValue !== previousValue) {
      console.log('Input value changed from', previousValue, 'to', inputValue);
      setPreviousValue(inputValue);
    }
  }, [inputValue, previousValue]);

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
    </div>
  );
}

In this example, we create a state variable inputValue using the useState hook. We also create another state variable previousValue to store the previous value of inputValue. Inside the useEffect hook, we compare the current and previous values of inputValue. If they are different, we log the change and update the previousValue.

4.2 usePrevious hook implementation

Continuing from the previous section, let’s reimplement the usePrevious hook with the updated code.

import { useRef, useEffect } from 'react';

export function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

We create a new file, ‘usePrevious.js’, and move the usePrevious hook code into it. By exporting the hook, we can import and use it in other components, as shown in the usage example above.

4.3 Example usage of the usePrevious hook

In this example, we’ll use the usePrevious hook in a component to track the previous prop value.

import React, { useEffect } from 'react';
import { usePrevious } from './usePrevious';

function DataFetcher({ data }) {
  const previousData = usePrevious(data);

  useEffect(() => {
    if (previousData !== data) {
      console.log('Data changed:', previousData, 'to', data);
    }
  }, [data, previousData]);

  return (
    <div>
      <p>Data: {data}</p>
    </div>
  );
}

In this example, we receive the prop ‘data’ in the DataFetcher component. We use the usePrevious hook to get the previous value of ‘data’ and store it in the previousData variable. Inside the useEffect hook, we log the change whenever ‘data’ is updated.

  1. Implementing usePrevious Hook

The usePrevious hook is a custom hook that allows us to track the previous value of a state or prop. By creating this custom hook, we can overcome the limitation of the useState hook and access the previous value whenever needed. Let’s explore how we can implement the usePrevious hook.

5.1 Understanding the concept of custom hooks

Custom hooks are JavaScript functions that utilize built-in hooks or other custom hooks to provide additional functionality to React components. They follow a naming convention of starting with the word “use” to indicate that they are hooks. Custom hooks allow us to encapsulate reusable logic and share it between components.

5.2 Creating the usePrevious hook

To create the usePrevious hook, we’ll start by importing the useRef hook from the ‘react’ package. The useRef hook allows us to create a mutable value that persists across re-renders without triggering a re-render itself.

Here’s an example implementation of the usePrevious hook:

import { useRef, useEffect } from 'react';

function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

In this code, we define the usePrevious function that takes a value as a parameter. We create a ref variable using the useRef hook and assign it to the ref constant. Then, we use the useEffect hook to update the ref.current value whenever the input value changes. By including [value] as the dependency array, we ensure that the effect is triggered only when the value changes. Finally, we return the ref.current value, which represents the previous value.

5.3 Usage example of the usePrevious hook

Now that we have implemented the usePrevious hook, let’s see how we can use it in a component.

import React, { useState } from 'react';
import { usePrevious } from './usePrevious';

function Counter() {
  const [count, setCount] = useState(0);
  const previousCount = usePrevious(count);

  return (
    <div>
      <p>Count: {count}</p>
      <p>Previous Count: {previousCount}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

In this example, we import the usePrevious hook from the ‘./usePrevious’ file (assuming it’s in the same directory). We declare a state variable called count using the useState hook. We then call the usePrevious hook, passing in the count variable, and store the result in the previousCount variable.

The current count and previous count are displayed in separate paragraphs within the component’s JSX. Whenever the count is updated by clicking the “Increment” button, the previousCount will reflect the previous value.

  1. Code Samples

In this section, we’ll provide additional code samples to illustrate the use of useState for tracking previous state and the implementation of the usePrevious hook.

6.1 useState example: Tracking previous state

Let’s say we have a form with an input field that updates a state variable called inputValue. We want to track the previous value of the inputValue and perform some actions based on its change.

import React, { useState, useEffect } from 'react';

function Form() {
  const [inputValue, setInputValue] = useState('');
  const [previousValue, setPreviousValue] = useState('');

  useEffect(() => {
    if (inputValue !== previousValue) {
      console.log('Input value changed from', previousValue, 'to', inputValue);
      setPreviousValue(inputValue);
    }
  }, [inputValue, previousValue]);

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
    </div>
  );
}

In this example, we create a state variable inputValue using the useState hook. We also create another state variable previousValue to store the previous value of inputValue. Inside the useEffect hook, we compare the current and previous values of inputValue. If they are different, we log the change and update the previousValue.

6.2 usePrevious hook implementation

Continuing from the previous section, let’s reimplement the usePrevious hook with the updated code.

import { useRef, useEffect } from 'react';

export function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

We create a new file, ‘usePrevious.js’, and move the usePrevious hook code into it. By exporting the hook, we can import and use it in other components, as shown in the usage example above.

6.3 Example usage of the usePrevious hook

In this example, we’ll use the usePrevious hook in a component to track the previous prop value.

import React, { useEffect } from 'react';
import { usePrevious } from './usePrevious';

function DataFetcher({ data }) {
  const previousData = usePrevious(data);

  useEffect(() => {
    if (previousData !== data) {
      console.log('Data changed:', previousData, 'to', data);
    }
  }, [data, previousData]);

  return (
    <div>
      <p>Data: {data}</p>
    </div>
  );
}

In this example, we receive the prop ‘data’ in the DataFetcher component. We use the usePrevious hook to get the previous value of ‘data’ and store it in the previousData variable. Inside the useEffect hook, we log the change whenever ‘data’ is updated.

By using the usePrevious hook, we can easily track and compare previous values of state or props in our React components. This provides flexibility and allows us to perform specific actions based on those changes.

  1. Using useState Hook

The useState hook is one of the most commonly used hooks in React. It allows us to add state to functional components. Let’s explore the basics of the useState hook and its limitations when it comes to tracking previous values.

7.1 Basics of useState Hook

The useState hook is imported from the ‘react’ package and can be used within functional components. It takes an initial state value as a parameter and returns an array containing the current state value and a function to update that state.

Here’s an example:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

In this example, we import the useState hook from the ‘react’ package. Inside the Counter component, we use the useState hook to declare a state variable called ‘count’ and its corresponding update function ‘setCount’. The initial value of ‘count’ is set to 0.

The current value of ‘count’ is displayed within a paragraph element. When the user clicks the “Increment” button, the ‘setCount’ function is called with the updated value (count + 1), which triggers a re-render and updates the displayed value.

7.2 Limitations of useState Hook for tracking previous values

Although the useState hook is powerful for managing state in React components, it doesn’t provide a built-in way to access the previous value of a state. It only gives us the current state value and a function to update it. This limitation becomes apparent when we need to compare the previous and current values of a state variable.

To overcome this limitation, we can create a custom hook called usePrevious, as discussed earlier. The usePrevious hook allows us to conveniently access the previous value of a state or prop in ReactJS applications.

By implementing the usePrevious hook, we can extend the capabilities of the useState hook and efficiently track the previous values of our state variables.

  1. Conclusion

In this blog post, we explored the concept of accessing the previous value of a state or prop in ReactJS applications. We discussed the limitations of the useState hook in this regard and introduced the usePrevious custom hook as a solution.

We learned how to create the usePrevious hook using the useRef and useEffect hooks from the ‘react’ package. The usePrevious hook allows us to conveniently access the previous value of a state or prop by storing it in a ref and updating it whenever the value changes.

Additionally, we provided code samples to demonstrate the implementation and usage of the usePrevious hook. We also touched upon the basics of the useState hook and its limitations when it comes to tracking previous values.

By utilizing the usePrevious hook, you can enhance your ReactJS applications by gaining access to the previous values of your state variables and props. This can be particularly useful in scenarios where you need to compare the previous and current values or perform specific actions based on state changes.

Previously at
Flag Argentina
Argentina
time icon
GMT-3
Seasoned Software Engineer specializing in React.js development. Over 5 years of experience crafting dynamic web solutions and collaborating with cross-functional teams.