Incorrect use of useEffect Example

In our playing card component, we made use of the hook useEffect. In this article, I will delve deeper into why this is an incorrect use of useEffect. By definition:

useEffect is a React Hook that lets you synchronize a component with an external system

https://react.dev/reference/react/useEffect

To understand this description of useEffect, we need to understand the terms used to describe it.

Our application’s component is the playing card and the external system is the application.

In our playing card example, the useEffect code looked like this:

useEffect(() => {
    suit === "Hearts" || suit === "Diamonds"
      ? setSuitColor("red")
      : setSuitColor("black");
  }, [suit]);  

The suit variable is a prop passed into the playing card. So the above useEffect is setting the suit colour based on that prop. But this doesn’t quite meet the definition of useEffect. There is no external system here, just props and the component’s state.

We could use the above code if the suit were updated based on something other than a user event, like when something is displayed on the screen. But in our case, updating the logic to remove the useEffect function call serves us better.

Refactoring away from useEffect

Inside the useEffect function above, we have the logic we want to maintain without useEffect. Namely, setting the colour of the card based on the suit.

The first step is to remove the useEffect call:

suit === "Hearts" || suit === "Diamonds" ? setSuitColor("red") : setSuitColor("black");

But by doing so, we will encounter the following too many re-renders error.

This makes a lot of sense if you stop and think about it.

The second parameter of useEffect stops the repeated calling of the useEffect function. The suit colour is set every time the component is rendered in our new code. This causes the component to re-render every time it is rendered, leaving us in an infinite loop.

So the logic needs to change a little to accommodate this.

We need only to set the suit colour if it differs from the current state variable suitColor. By adding this check, the state setting only occurs if needed. This check stops the infinite loop above from occurring.

if ((suit === "Hearts" || suit === "Diamonds") && suitColor != "red") {
    setSuitColor("red")
  } else if ((suit === "Spades" || suit === "Clubs") && suitColor != "black") {
    setSuitColor("black")
  }

Conclusion

It is very easy to fall into the trap of overusing useEffect. If you can define your UI during render, including setting values for all of your states, then you don’t need useEffect. It is not only unnecessary but also hurts the performance of your application for no gain.

If you missed the original playing card articles, you can find them here and here

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments