Let us see how to implement usePrevious hook in React.
usePrevious hook will take the current value as input and hold it and will return it whenever it will get a new value. For the initial render, it will return undefined
as there will not be any previous value for it.
To create the usePrevious hook we will need to use the useRef
and useEffect
hook together.
useRef
Between renderings, you can maintain values using the useRef
Hook which means the value won’t change or be lost when the React components re-render. This will help us to persist the previous value.
useEffect
With the useEffect
hook, we can manage the side effects in the components during the lifecycle events.
Thus we can create a new reference using useRef
and update its value inside the useEffect
whenever a new value is provided, at the end return the reference value.
function usePrevious(value) { // create a new reference const ref = useRef(); // store current value in ref useEffect(() => { ref.current = value; }, [value]); // only re-run if value changes // return previous value (happens before update in useEffect above) return ref.current; }
current
is the default object available on each reference that is used to store any value.
Because the ref.current
is returned before the useEffect
update, it return the previous value, by default there is no value for ref.current
thus it returns undefined
.
Test case
import { useState, useEffect, useRef } from "react"; const usePrevious = (value) => { // create a new reference const ref = useRef(); // store current value in ref useEffect(() => { ref.current = value; }, [value]); // only re-run if value changes // return previous value (happens before update in useEffect above) return ref.current; }; const Example = () => { const [count, setCount] = useState(0); // get the previous value passed into the hook on the last render const prevCount = usePrevious(count); // show both current and previous value return ( <div> <h1> Now: {count}, before: {prevCount} </h1> <button onClick={() => setCount(count - 1)}>Decrement</button> </div> ); }; export default Example;