Implement the useStateWithReset custom hook in React



This content originally appeared on DEV Community and was authored by Debajit Mallick

Introduction

In React, useState is a go-to hook for managing component state. But often, especially in forms or interactive UIs, we wish there was a built-in reset function that resets the state back to its original value—just like hitting a “Reset” button.

That’s where a custom hook like useStateWithReset becomes useful.

In this blog, we’ll walk through the step-by-step creation of a useStateWithReset hook and see how to use it in a real-world scenario.

Question

Create a custom hook useStateWithReset that:

  • Takes an initial value (or lazy initializer function) just like useState
  • Returns the same values as useState, plus a third value: a reset() function
  • This reset() resets the state back to its original value

useStateWithReset Hook

import { useCallback, useMemo, useState } from 'react';

const useStateWithReset = (initialStateOrInitializer) => {
  const initialState = useMemo(() => {
    if (
      typeof initialStateOrInitializer === 'function' &&
      initialStateOrInitializer.length === 0
    ) {
      return initialStateOrInitializer();
    }
    return initialStateOrInitializer;
  }, []);

  const [value, setValue] = useState(initialState);

  const reset = useCallback(() => {
    setValue(initialState);
  }, [initialState]);

  return [value, setValue, reset];
};

export default useStateWithReset;

Now, let’s understand the code step by step:

1. Accepting Initial State or Initializer Function:

const useStateWithReset = (initialStateOrInitializer) => {

Just like useState, this hook supports both:

  • A primitive or object value: useStateWithReset(0)
  • A lazy initializer function: useStateWithReset(() => expensiveInit())

2. Memoizing the Initial Value:

const initialState = useMemo(() => {
  if (
    typeof initialStateOrInitializer === 'function' &&
    initialStateOrInitializer.length === 0
  ) {
    return initialStateOrInitializer();
  }
  return initialStateOrInitializer;
}, []);

Why this step?

  • We want to evaluate initializer function once, not on every re-render.
  • initialStateOrInitializer.length === 0 checks that the function takes no arguments (like a () => value), mimicking how React handles lazy initial state.
  • useMemo ensures the initial value is computed once and preserved.

3. Using useState with the Computed Initial State

const [value, setValue] = useState(initialState);

Simple usage of useState, but with the precomputed and memoized initialState.

4. Creating the Reset Function with useCallback:

const reset = useCallback(() => {
  setValue(initialState);
}, [initialState]);
  • We create a memoized function that resets state to the original value.
  • useCallback ensures the function reference stays stable unless initialState changes.

5. Returning Value, Setter, and Reset:

return [value, setValue, reset];

This mirrors the API of useState, but with a third item: reset.

Example Usage

import React from 'react';
import useStateWithReset from './useStateWithReset';

const ProfileForm = () => {
  const [name, setName, resetName] = useStateWithReset('John Doe');

  return (
    <div>
      <h2>Edit Profile</h2>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <button onClick={resetName}>Reset</button>
    </div>
  );
};

export default ProfileForm;

You can update the name by typing. Click “Reset” and it will go back to “John Doe”—just like magic!

When to Use useStateWithReset

  • Forms that need a clear or reset button
  • Repeating workflows that need to restore initial state
  • Complex UI interactions where initial state must be preserved
  • Interview questions around custom hooks and state abstraction

Conclusion

The useStateWithReset hook is a powerful yet simple abstraction that extends the basic useState with an extra reset() function. If you liked this blog and want to learn more about Frontend Development and Software Engineering, you can follow me on Dev.


This content originally appeared on DEV Community and was authored by Debajit Mallick