Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
import { useState, useEffect, useRef } from 'react';
// Usage
function App() {
// State value and setter for our example
const [count, setCount] = useState(0);
// Get the previous value (was passed into hook on last render)
const prevCount = usePrevious(count);
// Display both current and previous count value
return (
<h1>Now: {count}, before: {prevCount}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
// Hook
function usePrevious(value) {
// The ref object is a generic container whose current property is mutable ...
// ... and can hold any value, similar to an instance property on a class
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;

This comment has been minimized.

Copy link

ianobermiller commented Nov 9, 2018

Love all the comments in the custom hook function!


This comment has been minimized.

Copy link

ritwickdey commented Nov 14, 2018

Just an optimization, not sooooo inportant

useEffect(() => {
    ref.current = value;
  }, [value]); // only run if and only if value is changed

This comment has been minimized.

Copy link
Owner Author

gragland commented Nov 20, 2018

@ritwickdey Thanks, code updated!


This comment has been minimized.

Copy link

olee commented Dec 30, 2018

I wrote the following alternative which (even if it looks a bit complicated) can get around with just a single useState and should increase performance a lot because it does not need to check if the effect needs to run on every render.

import { useState, Dispatch, SetStateAction } from 'react';

type SetStateFn<T> = (previousValue: T) => T;

type IValueWrapper<T> = [
    /** value */
    /** setValue */
    /** previousValue */
    T | undefined

 * Drop-in replacement for react useState which also returns previousValue.
 * @return [value, setValue, previousValue]
export default function useStateWithPrevious<T>(initialValue: T) {
    const createSetStateDispatch: (previousValue: T) => Dispatch<SetStateAction<T>> = previousValue => value => {
        const newValue = typeof value === 'function' ? (value as SetStateFn<T>)(previousValue) : value;
    const [valueWrapper, setValueWrapper] = useState<IValueWrapper<T>>(() => [
    return valueWrapper;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.