DEV Community

Cover image for React and effect hook
Kristijan Pajtasev
Kristijan Pajtasev

Posted on

8 5

React and effect hook

After the hook introduction post and state hook post, it is time to cover the effect hook. The reason why it is called useEffect is that it lets you perform side-effects after component mounts. Those can be loading data from the server, adding a custom window listener, or anything else you would do at that stage.

Basic usage

The most basic usage would be running it each time component renders. Maybe you need to an event listener on an element that recreates each time. If you want to run it after each time component renders, you can use the effect hook and only pass a function as a parameter.

import {useEffect, useState} from 'react';
function Counter() {
const [counter, setCounter] = useState(0);
useEffect(() => {
console.log("This useEffect runs on every change");
})
return (
<div>
<div>useEffect - simplest version</div>
<div>{counter}</div>
<div>
<button onClick={() => setCounter(counter + 1)}>
Increment
</button>
</div>
</div>
)
}
view raw Counter.js hosted with ❤ by GitHub

A component is re-rendered each time its state or prop changes. That means in the example above, each time counter value changes, useEffect also executes.

Cleanup

Another thing you could do in the effect hook is subscribing to an API. But that is an action that you would undo when no longer needed. If the hook is triggered each time, you don't want to have multiple subscriptions run. That is why the function you give to a hook can return function. If you do that, this new returned function executes when the component is unmounted. You can use it as a cleanup task - something like unsubscribing from API or removing event listener.

import {useEffect} from 'react';
import ChatAPI from './ChatAPI';
function ChatComponent() {
useEffect(() => {
ChatAPI.subscribe();
return () => {
ChatAPI.unsubscribe();
}
})
return <div>Chat Component</div>
}

I do want to point out once again. Return value needs to be function. I see many developers trying to return the result of the executing function instead of wrapping it into a function.

Conditional execution

As said before, each time component renders the effect hook runs. But what if you don't want it to run? Maybe you have two state variables, and you want to run a task only when one of them changes. Effect hook also takes the second parameter, an array of all objects. If you do that, the hook runs the first time component renders and re-run each time any element of the array is updated.

import {useEffect, useState} from "react";
import Counter from "./Counter";
function ConditionalEffects() {
const [firstCounter, setFirstCounter] = useState(0);
const [secondCounter, setSecondCounter] = useState(0);
useEffect(() => {
console.log("updated first counter")
}, [firstCounter]);
return (
<div>
<Counter onChange={setFirstCounter} />
<Counter onChange={setSecondCounter} />
</div>
)
}

In the example above, there are two counters, each connected to its state value. Because the effect hook has only the first counter value in a list, it runs only when the first counter changes. This feature helps if we have different tasks for each update. Suppose there is a different task you need to do for the second counter. You could add another effect hook reacting only its change.

import {useEffect, useState} from "react";
import Counter from "./Counter";
function ConditionalEffects() {
const [firstCounter, setFirstCounter] = useState(0);
const [secondCounter, setSecondCounter] = useState(0);
useEffect(() => {
console.log("updated first counter")
}, [firstCounter]);
useEffect(() => {
console.log("updated first counter")
}, [secondCounter]);
return (
<div>
<Counter onChange={setFirstCounter} />
<Counter onChange={setSecondCounter} />
</div>
)
}

Run once

There are situations when you might want to run the effect hook only once. Make some requests, broadcast an event, or anything else. To achieve that, you can use a particular case of conditional form. If you pass just an empty array, the hook runs the first-time component renders. But since there are no elements inside, it won't run again.

import {useEffect} from 'react';
function OneRun() {
useEffect(() => {
console.log("Runs only once.")
}, []);
return <div>One run</div>
}
view raw OneRun.js hosted with ❤ by GitHub

You can find code from this post in my GitHub repository.


For more, you can follow me on Twitter, LinkedIn, GitHub, or Instagram.

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs