A usePrevious Hook returns the value a variable held during the previous render. It stores the last seen value in a ref and updates it after each commit, so callers can compare past and present inside an Effect.
It is a comparison tool, not a second source of state. A ref update never triggers a re-render, so the Hook is cheap but invisible to React.
Build the Hook
A ref holds the last value between renders, and an Effect writes the new value after each commit. That ordering is what makes the returned value lag one render behind.
import { useEffect, useRef } from "react";
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}The ref survives re-renders, unlike a plain local variable. The Effect runs after the commit, so during the current render ref.current still holds the previous value, and the return hands that older value back.
Compare past and present in an Effect
The most common use is detecting a change inside an Effect, where the previous value is safe to read.
function Player({ currentSong }) {
const previousSong = usePrevious(currentSong);
useEffect(() => {
if (previousSong !== currentSong) {
document.title = `Playing: ${currentSong}`;
}
}, [previousSong, currentSong]);
return <h2>{currentSong}</h2>;
}When the song prop changes, the comparison inside the Effect sees two different values and updates the browser tab title. The browser title is an external system, so an Effect is the right place for that work.
The previous value is read inside the Effect, not rendered. The same comparison can drive analytics or subscriptions that must react to a change.
Know when not to use it
- Do not render the previous value, because that reads a ref during render.
- Do not use it to setState in an Effect when a prop changes. Reset with a key instead.
- If the past value affects rendering, store it in state during render, or derive the result directly.
A usePrevious Hook is for comparisons, not for keeping two values in sync. When the past value must appear on screen, keep the previous value in state during render instead of reading a ref that React does not track. If a prop change should reset state, pass a key to remount the component instead of comparing the old value in an Effect.
Store previous state during render when it renders
When the previous value must appear in the UI, keep it in state and set it during render. React re-renders immediately when state is set during render, so the screen never shows a stale intermediate value. This pattern is for render output, while usePrevious stays for Effect comparisons.
See how to create a custom Hook for the extraction steps, and useRef explained for how refs persist between renders.
Rune AI
Key Insights
- Store the last value in a ref and update it in an Effect.
- Read the result only inside Effects or event handlers.
- Do not render the previous value, which reads a ref during render.
- Do not use it to adjust state in an Effect when a prop changes.
- Prefer a key or render-time state for past values that affect output.
Frequently Asked Questions
Why does usePrevious return the previous value?
Can I render the previous value returned by usePrevious?
When should I not use usePrevious?
Conclusion
A usePrevious Hook stores the last seen value in a ref and updates it after each commit, so callers can compare the previous and current values inside an Effect. Use it for comparisons, not for rendering, and prefer state or a key when the past value drives output.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.