React hooks: useEffect()

Part 2: diving into useEffect()

Abdo Amin
4 min readMay 5, 2023

In this article, I want to address two points in relation to useEffect:

  • Why?
  • How?
React hooks

The Why?

React components are functions, you provide them with input (props) and expect a predictable output.

const Profile = ({ name, age }) => {
return (
<div>
<span>name: {name}</span>
<span>age: {age}</span>
</div>
);
};

Looking at the code above, if you used it like below, you should expect the Profile component to display an output of name: “John” and age: 24.

const App = () => {
return <Profile name="John" age={24} />
}

The above is called “Pure function”, in short, pure functions are predictable functions, given the same input they will always return the same output.

The second rule of a pure function is: it has no side effects.

A few examples of side effects are:

  • fetch and web APIs (setTimeout, setInterval, …etc)
  • DOM mutation

And here comes the why…useEffect allows you to run side effects in your React component without blocking the component flow.

What I mean by component flow, is that the effects don’t interfere with the component rendering. useEffect runs after the component has been rendered, thus it is non-blocking.

To sum up, useEffect allows you to write non-blocking side effects in your component.

Why is it important? Because it allows your app to have an asynchronous beauty to it. Would you rather have your user blocked out of using the application while waiting for the data to be fetched? or would you prefer them to have the request run in the background while the app is responsive and interactive in the foreground?

The How?

Before React hooks came to light, we had 3 bad boys:

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

ComponentDidMount would run after the component's initial render.

ComponentDidUpdate would run after each component’s re-render.

ComponentWillUnmount would run just before the component is about to be removed.

They ought to be used depending on the “timing”.
You need to run something only once the component is rendered and that’s it? Maybe a fetch request, then componentDidMount would have been your choice.
If you wish to run something when to run once and every time a prop is changed, then componentDidUpdate would do the job.
The component is about to be removed from the dom? then componentWillUnmount would be the resort.

Now, things are pretty much easier. Or so I think.
React combined those 3 bad boys into one big bad boy and named him useEffect

Let’s see how we could use useEffect to have the same advantage that was given to us by the 3 bad boys.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

ComponentDidMount in React hooks

To replicate componentDidMount or in other words, have a side effect run only once as soon as the component is rendered. We would write:

useEffect(() =>{
// code goes here...
}, [])

Your eyes caught that we pass two arguments, first a function that has the effects you want to execute, second an array.

The array is called a “dependency array”, in simple words, run this code when any dependency in the array changes. Since it is empty, it will only run once.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

ComponentDidUpdate in React hooks

If you paid enough attention to the previous example, you would know that all you would have to do is to provide a prop/state/variable to the dependency array change to configure useEffect re-run whenever a dependency changes.

const [state, setState] = useState(...)

useEffect(() => {
// code goes here...
}, [state])

Now, whenever statechanges this useEffect will execute.

Important note: the code above will run on initial render and every time statechanges. Thus, it is a combination of componentDidMount and componentDidUpdate

Buuuuuut…What if I want to run an effect everytime the component re-renders and not a specific state/prop? Like all the time!

Simple, don’t provide a dependency array!

useEffect(() => {
// code goes here...
})

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

ComponentWillUnmount in React hooks

This one is mainly used for cleanup, you know stuff like clearTimeout, cancel fetch request, unsubscribe…etc.

useEffect(() => {
const timer = setTimeout(() => {}, 1000);
return () => {
// rest of cleanup goes here...
clearTimeout(timer)
}
}, [])

It is simple, just return a function. The cleanup function will only run when a component is about to be removed.

I could write further, but I am in short in time.

Thank you for reading.

--

--

Abdo Amin

I love React and anything that has JavaScript and frontend in it.