Resetting state in a React application is a common thing to do. You get some new data in your props, and you want to set your state back to the initial values, and often it is done with useEffect. However, useEffects can be messy and hard to understand, and it's because you (and I) are using them wrong (🔥). Let's take a look at how to solve this in a better way by using the key attribute.
The content of this article is heavily inspired by the new React docs (which is in beta).
Resetting state with useEffects
When a user is navigating through your application you may want to reset some of the state to show the correct data. Take a look at the example below of a simple article component:
function Article({ articleId }) {
const [likes, setLikes] = useState(0)
useEffect(() => {
setLikes(0)
}, [articleId])
/** Rest of component */
}
In the code above you have the Article
component which gets an articleId
as a prop, and you have a local state keeping track of the number of likes a user wants to give the article. We also have a useEffect that listens to the articleId
and resets the value of likes
whenever it changes. This is because we want to give the user a clean slate when he or she navigates to another article and wants to rate that article as well. This is a simple case, but it is pretty annoying to have the useEffect which must monitor the articleId
, and reset everything whenever it changes. And it doesn't end there, because all child components for the Article component must also have the logic of resetting state to make sure all data is related to the same article further down the tree.
The useEffect hook is handy, but in most cases, you don't need it. UseEffects are for synchronizing effects, not setting state back to their default values. Let's look at how and why using the key attribute instead of a useEffect will save your application from many unnecessary lines of code and re-renders.
You don't need useEffects everywhere
The useEffect hook in React is a JavaScript function which is intended to synchronise your effects with the state in your component. Side effects are functions used to communicate with things outside of your component.
Some common examples are data fetching or timing functions like setTimeout and setInterval.
Resetting state with the key attribute
The key attribute is commonly used when rendering a list of items in React. Maybe you have seen a warning in your console saying Warning: Each child in a list should have a unique "key" prop
, telling you to add a unique key to the siblings of components. This is to help React identify a specific component in a list of components, making sure to update the correct item when changes are made to the list (i.e. filtering or removing items in the list).
In addition to using key on list elements, you can use it on individual components as well. This will solve our case with resetting case because instead of forcing new data on the same mounted component and resetting every state with useEffect, React will create a new instance of the component for each key. Read more about the key attribute in the React beta documentation for more information.
Let's add the key attribute to the component in the example above to reset the state. Take a look at the example below:
function ArticleContainer({ articleId }) {
return (
<Article key={articleId} articleId={articleId} />
)
}
function Article({ articleId }) {
const [likes, setLikes] = useState(0)
/** Rest of component */
}
That's it! You add an attribute and you can drop the redundant useEffect 🎉.
For more info, look at this neat article about resetting state from the React documentation.
TL;DR
Use the key attribute on a component to reset all state in a component, not the useEffect hook – useEffects are for side effects and not state updates.