• React
    • Architecture
    • Pro Tips

    React key Prop vs State: Reset a Component

    By Published Updated 6 min read

    Reset a React component's state by changing its key instead of syncing props in useEffect, with a runnable example and when not to.

    To reset a React component's state when it should represent something new, such as a different user, give it a key that changes, like key={user.id}. When the key changes, React unmounts the old instance and mounts a fresh one, so every piece of state starts over from its initial value. Copying new props into state with useEffect also works, but it renders once with stale values and is easy to get wrong (React docs: resetting all state when a prop changes).

    Key takeaways

    • A changed key tells React to discard a component, including all the state in its subtree, and mount a new instance.
    • Resetting state inside useEffect renders once with stale state before the effect corrects it, and every new state variable must be reset by hand.
    • Use a key when the component now represents a different entity: another user, a fresh form, a different document.
    • When the entity is the same and only its data changed, read props directly or derive values during render instead of copying props into state.

    Why would you need to reset a component?

    In a React application, you often need to "reset" a component to its initial state. This sounds simple, but there are two very different ways to do it, and choosing the wrong one can lead to bugs or messy code.

    The two competing patterns are:

    1. Syncing with an effect: Keep the component mounted and use useEffect to copy new props into state.
    2. Remounting with a key: Change the component's key prop so React replaces it with a fresh instance.

    Let's look at both approaches, what they cost, and when to use which.


    Approach 1: Syncing state with useEffect

    This is what many developers reach for first. You keep the component mounted and ask it to update its internal data when a prop changes.

    function UserForm({ user }) {
      const [name, setName] = useState(user.name);
      const [email, setEmail] = useState(user.email);
    
      // Sync state when the prop changes
      useEffect(() => {
        setName(user.name);
        setEmail(user.email);
      }, [user]);
    
      return <form>...</form>;
    }
    

    What goes wrong with the effect approach?

    At first glance, this looks fine. But as the component grows, the pattern becomes hard to maintain.

    1. Forgotten state: If you add another piece of state (for example, hasUnsavedChanges), you must remember to reset it in the effect too. Forget, and the form shows leftovers from the previous user.
    2. A render with stale data: Effects run after React has rendered. When user switches from User A to User B, React first renders UserForm with User B's props but User A's name and email state. The effect then sets new state, which triggers a second render. The stale output can briefly appear on screen.
    3. Unexpected resets: The effect depends on the user object. If the parent creates a new user object on every render, the effect fires each time and wipes out whatever the person has typed.
    4. Duplicated logic: You write initialization twice: once in useState(initial) and again in the effect.

    Approach 2: Resetting state with a key

    React uses the key prop to tell elements of the same type apart. You usually see keys in lists rendered with map, but you can put a key on any component (React docs: resetting state with a key).

    If the key changes between renders, React treats the element as a different component instance:

    1. It unmounts the old instance, running effect cleanups and discarding its state and the state of every component inside it.
    2. It mounts a new instance, running state initializers and effects from scratch.
    function UserDashboard({ currentUser }) {
      return (
        <div>
          {/*
            When currentUser.id changes, React destroys the old UserForm
            and creates a brand-new one.
            State is reset automatically!
          */}
          <UserForm key={currentUser.id} user={currentUser} />
        </div>
      );
    }
    
    function UserForm({ user }) {
      // No useEffect needed!
      // This initial value is used fresh every time the key changes.
      const [name, setName] = useState(user.name);
    
      return <form>...</form>;
    }
    

    What are the benefits of the key approach?

    1. Nothing to maintain: Every state variable, including ones you add later, resets automatically.
    2. No stale render: The new instance renders with the new props from its very first render.
    3. Simpler components: UserForm initializes its state once and doesn't need to know that it can be reset.

    What does remounting cost?

    Remounting recreates the component's DOM nodes and throws away everything inside it, including uncontrolled input values, focus and scroll position. For a form that switches users, that's exactly what you want. For large subtrees that change often, a remount is more work than a regular update, so reserve key changes for genuine changes of identity.

    Try it: reset a counter with a key

    Paste this into the React playground. Click the counter a few times, then click Reset:

    import { useState } from "react";
    
    function Counter({ label }) {
      const [count, setCount] = useState(0);
      return (
        <button onClick={() => setCount(count + 1)}>
          {label}: {count}
        </button>
      );
    }
    
    export default function App() {
      const [version, setVersion] = useState(0);
    
      return (
        <div>
          <Counter key={version} label="Clicks" />
          <button onClick={() => setVersion(version + 1)}>Reset</button>
        </div>
      );
    }
    

    Counter has no reset logic at all. Incrementing version gives it a new key, so React mounts a fresh instance with count back at 0.


    When should you use the key pattern?

    Use a key when the identity of what the component represents changes.

    • Switching entities: Moving from Profile A to Profile B, or from one chat conversation to another.
    • Resetting a form: After a successful submission, increment a formVersion number used as the key to clear every input.
    • Restarting a component: Replaying an animation or restarting a timer from the beginning.

    When don't you need a key reset?

    If the component still represents the same thing and only its data has changed, you usually don't need to copy props into state at all.

    • Real-time values: A stock ticker receiving a new price. Render the price prop directly. Remounting would throw away the chart's internal state for no reason.
    • Derived values: Compute filtered lists or formatted text during render from props and state, and wrap the calculation in useMemo only if it is expensive.
    • Typing: A search box that updates a filter as the user types is ordinary state, not a reset.

    If you truly need to adjust part of the state when a prop changes, the React docs show how to do it during rendering instead of in an effect (React docs: adjusting some state when a prop changes).

    Summary

    • Updating (same identity): Let React diff the new props and state, and derive what you can during render.
    • Remounting with a key (new identity): The cleanest way to reset a component when it represents something new.

    Next time you find yourself writing a complex useEffect just to reset a form, stop and ask yourself: "Is this a different entity?" If the answer is yes, use a key.

    To see where keys fit into React's diffing, read Virtual DOM vs real DOM in React. For what runs when a fresh instance mounts, see React useState lazy initialization explained.

    Frequently asked questions

    How do I reset a React component's state?

    Render the component with a key that changes whenever it should start over, such as a user ID or a number you increment. When the key changes, React unmounts the old instance and mounts a new one, so all of its state, and the state of its children, returns to the initial values automatically.

    Does changing the key remount a component?

    Yes. React uses the key together with the component type to decide whether an element is the same instance as before. A different key means a different instance, so React runs cleanup for the old one, removes its DOM nodes and mounts a new instance with fresh state and effects.

    Why shouldn't I reset state inside useEffect?

    Effects run after React has rendered, so the component first renders with stale state and then renders again once the effect updates it. That wastes a render, can briefly show outdated data and requires resetting every state variable by hand. Changing the key avoids all three problems with less code.

    Is remounting with a key bad for performance?

    Remounting recreates the component's DOM and discards all of its internal state, so it does more work than a small update. For a typical form or panel the extra work is small, but avoid changing keys on large subtrees that update frequently, and use a key change only when the component represents something new.

    Try the examples yourself

    Open the React playground to run and edit code from this article in your browser. There is nothing to install and no account to create.