React useEffect “best practices”

Introduction

Hi everyone, surely everyone among React Developers knows about a react-hook, a very special hook, a concept that many people discuss and even in the title of the blog post, it already reveals the name of that hook, which is none other than useEffect. And today, let’s deep dive into it. Let’s go!!!

useEffect is one React API, and built-in React core. According to the blog’s title “best practices”, normally known as practice, training with the “best” way, or using it properly, reasonably, not “stupid”. With a title that sounds “only for newbies”, but in this blog instead of showing cases that use useEffect in our react app, we avoid using useEffect. Ohh, why do we avoid one most popular API developed by React team? Let’s research with me ❤️

Before we go to cases that needn’t use useEffect. Let’s have a look together at one concept that I guest any React Dev need to know. It’s React-lifecycle concept.

I have “stolen” one diagram that represents the lifecycle in React here

 

This diagram is designed by one member in React Dev team reference

We can easily see the progress of Render and Commit phase in the left column and inside each progress, they also describe the event’s action.

It will take a lot of time to explain behind the scene each step, so I design a “lite” diagram to make lifecycle’s diagram simplify

 

Component just like us. Having birth stage (componentDidMount), growing stage (componentDidUpdate), and the last one is “dead” (componentWillUnmount). So, do we gumshoe, and catch the mutation component progress? Fortunately, the react-hook which we mention in this blog can do. Is this hook potential and powerful, right?

In addition to the inherent benefit that this hook brings, it still has some latent surrounding app’s performance. Effects are an escape hatch from the React paradigm, and I call “black sheep”. They let you “step outside” of React and synchronize your components with some external system like a non-React widget, network, or the browser DOM. Read more

Coming back to the main issue, here we will mention some ways we can avoid useEffect out of our react app that I feel is effective and particular to me.

Updating state based on props or state

Suppose you have a component with two state variables: firstName and lastName. You want to calculate a fullName from them by concatenating them. Moreover, you’d like fullName to update whenever firstName or lastName changes. Your first instinct might be to add a fullName state variable and update it in an Effect:

 

This is more complicated than necessary. It is inefficient too: it does an entire render pass with a stale value for fullName, then immediately re-renders with the updated value. Remove the state variable and the Effect:

Adjusting some state when a prop changes

Let’s say we have a <Bar/> component and that component’s state depends on the props of the parent component passed down. In the case below, <Bar/> takes count props. And in the <Boo/> component we have a state of count and a button to increase the value of count by one.

 

In the above code, do you realize that there is a problem here? Come ****here then try clicking “Click” to see if the count is added. And… no change here, why is that? Initial tempCount only receives the count value passed in the first time as the initial value, the next updates of count, the tempCount variable will not change by itself, but we will need to use setTempCount to update.

In order for the <Boo/> component to update the tempCount every time up to date, we need to use useEffect with the dependencies count props so that every time the count changes, we will use setTempCount to update the tempCount again. The feeling of useEffect is something evil that makes it easy for us to hold and use it. Again, let’s try in here one more time!

 

Okay so the problem of <Bar/> not updating state has been solved. But this way may not be the best way or best practice. Since we’re avoiding using useEffect, I won’t go this route anymore. So how? The suggestion for you is that there is a keyword “key”, remember this keyword? We often use key as a props passed to the component each time we map an array and then render each element of that array. Read more

 

Let me remind you a little bit about the use of the key keyword in React. “Key” is a special props defined by React, this “key” helps React to optimize both rendering and re-render performance. Component update is based on the Diffing Algorithm of the topic Reconciliation to find the differences in a DOM tree and then just update the things that need to change and keep the same elements.

Here, we have a simple example to make it easier to visualize. In the ul element, there is a list of li contains the names of people. Suppose when we add a person to that list, entire list will be re-rendered instead of rendering each newly added element. And here “key” will be the solution to handle the “redundant” re-render. When child elements have props as keys, React uses these keys to check if the child elements in the root tree match the child elements in the sub-tree. For example, adding “key” to the example that didn’t work above could make the tree conversion more efficient:

Now React knows that the element whose key is “2014” is a new element so it will just render that element. Pretty good right? React will rely on this key to compare whether in these lists there are elements that have changed or been added to update in the most optimized way. Now let’s go back to the original problem. So how can we use “key” to replace useEffect here is this case? Very simple, we just need to pass the key with the value is count.

By this way <Boo/> will notice the change and then unmount the component and then re-mount the component. The work will ensure that tempCount is always fetched the newest value.

So we have removed useEffect from the code and the code looks pretty cleaner. However, this method does not completely replace useEffect in all cases because the mutate mechanism of this <Bar/> component is completely different. With using effects, the component will be unmount → update. As for using the key, the component will be completely re-mounted. So we also need to further evaluate which way would be more appropriate in the situation that we are in.

Summary

Effect is really a concept that probably everyone in React Dev need to know, but to be able to understand and apply it in a controllable, efficient and optimal way, we need … go here ?

LongPC

Comments

Let’s make a great impact together

Be a part of BraveBits to unlock your full potential and be proud of the impact you make.