Using key prop to reset React components
Sometimes, solutions to some of the problems are much simpler than we make them to be. Working with React.js is one of those things where you may complicate things unnecessarily when you don’t know the right approach.
Take the following scenario for example.
The problem
Let’s say we have a <ModalPopup>
component like so.
import React, { useState } from "react";
import { FormComponent } from "./FormComponent";
export function ModalPopup() {
const [selectedUser, setSelectedUser] = useState("");
const users = [
{
id: 1,
name: "Amit Merchant"
},
{
id: 2,
name: "John Doe"
}
];
return (
<>
<div>
<label>Select a user: </label>
<select onChange={(e) => setSelectedUser(e.target.value)}>
<option>Select a user</option>
{users.map((user) => (
<option key={user.name}>{user.name}</option>
))}
</select>
</div>
<div>
<FormComponent name={selectedUser} />
</div>
</>
);
}
As you can tell, the <ModalPopup>
component renders a select menu of users. Upon selecting a user, we pass in the selectedUser
to a child component called <FormComponent>
that looks like so.
import React, { useState, useEffect } from "react";
export function FormComponent({ name }) {
const [type, setType] = useState(
name === "John Doe" ? "Admin" : "Super Admin"
);
return (
<>
{name && (
<div>
<br />
Selected user: <b>{name}</b>
<br />
Type: <b>{type}</b>
</div>
)}
</>
);
}
Here, in the <FormComponent>
component, we are rendering the name
of the selected user that we passed in as a prop from the <ModalPopup>
component.
On top of this, we are also initiating an internal state for setting the type
of the user using the useState
hook. Notice that the value type
is dependent on the name
prop. So, when we select a user, the <FormComponent>
component will render the name
and type
of the selected user. This is fine!
But the problem arises when you select another user, only the name
will be rerendered and not the type
. Why? That is because the internal state of the <FormComponent>
component will only be initiated once when the component mounts. It doesn’t get updated when the name
prop is changed.
Using the useEffect
hook
To fix this, we can introduce the useEffect
hook in the <FormComponent>
component and update the internal state like so.
useEffect(() => {
setType(name === "John Doe" ? "Admin" : "Super Admin");
}, [name]);
We passed in name
as one of its dependencies for useEffect
. So, when name
is changed, the type
will also be updated every time a different user is selected. Here’s everything in action.
And so, the problem is solved, right? Yes and No!
As you can tell, we have a bit of duplication going in the useEffect
hook just to “reset” the internal state of the <FormComponent>
component. Is there an efficient way to do this? Yes!
Enter the key
prop!
Using the key
prop
To immediately reset the entire component,
All we need to do is to provide a unique
key
prop to the component that we want to get reset. That also includes resetting the internal states of that component.
So, if we want to reset the internal state of the <FormComponent>
component in our previous example, we can pass in a key
prop to it like so.
<FormComponent key={selectedUser} name={selectedUser} />
And then we can remove useEffect
from the <FormComponent>
component entirely since the state of type
will be reset everytime a new user is selected.
import React, { useState } from "react";
export function FormComponent({ name }) {
const [type] = useState(name === "John Doe" ? "Admin" : "Super Admin");
return (
<>
{name && (
<div>
<br />
Selected user: <b>{name}</b>
<br />
Type: <b>{type}</b>
</div>
)}
</>
);
}
Here’s everything in action!
Like this article?
Buy me a coffee👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.