How to only call a function Once in React

avatar
Borislav Hadzhiev

Last updated: Apr 6, 2024
3 min

banner

# Only call a function Once in React

Use the useEffect hook to only call a function once in React. When the useEffect hook is passed an empty dependencies array, it is only run when the component mounts.

This is the preferred approach when you have to fetch data when the component mounts.

App.js
import {useEffect, useState} from 'react'; const App = () => { const [num, setNum] = useState(0); useEffect(() => { // ๐Ÿ‘‡๏ธ Only runs once console.log('useEffect ran'); function incrementNum() { setNum(prev => prev + 1); } incrementNum(); }, []); // ๐Ÿ‘ˆ๏ธ Empty dependencies array return ( <div> <h2>Number is {num}</h2> </div> ); }; export default App;

only call function once in react

The code for this article is available on GitHub

The incrementNum function is only called once - when the component mounts.

The second parameter we passed to the useEffect hook is an array of dependencies.

The first parameter is a function that gets invoked when the component mounts and any time the dependencies in the array change.

We specified an empty array of dependencies, so the function we passed to the useEffect hook will only be called once.

Notice that we defined the incrementNum function inside of the function we passed to the useEffect hook.

We did this, so we don't have to add the function to the hook's dependencies array.

Alternatively, we could have defined the function outside of the component or memoized it.

# Fetching data only once

Here is an example of how you would call a function to fetch data only once - when the component mounts.

App.js
import {useEffect, useState} from 'react'; const App = () => { const [data, setData] = useState({data: []}); const [err, setErr] = useState(''); useEffect(() => { // ๐Ÿ‘‡๏ธ This only runs once console.log('useEffect ran'); // ๐Ÿ‘‡๏ธ fetch data from remote API async function getUsers() { try { const response = await fetch('https://reqres.in/api/users', { method: 'GET', headers: { Accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } const result = await response.json(); console.log('result is: ', JSON.stringify(result, null, 4)); setData(result); } catch (err) { setErr(err.message); } } getUsers(); }, []); // ๐Ÿ‘ˆ๏ธ Empty dependencies array console.log(data); return ( <div> {err && <h2>{err}</h2>} {data.data.map(person => { return ( <div key={person.id}> <h2>{person.email}</h2> <h2>{person.first_name}</h2> <h2>{person.last_name}</h2> <br /> </div> ); })} </div> ); }; export default App;

fetching data only once in react

The code for this article is available on GitHub

We defined a getUsers function inside of the useEffect hook. The function is called only once - when the component mounts and makes a single request to a remote API to fetch some data.

The useEffect hook is run only once because we passed it an empty dependencies array as the second parameter.

If you need to fetch data on button click, check out the following article.

# Define the function outside of the component

An alternative to defining the function you want to only call once inside of the useEffect hook is to define the function outside of the component.

If the function is defined outside of the component, it won't get re-created every time the component renders and will be stable and therefore doesn't have to be added to the hook's dependencies array.

# Using the useCallback hook to memoize the function

Alternatively, you can use the useCallback hook to memoize the function and pass it to the dependencies array of useEffect.

App.js
import {useCallback, useEffect, useState} from 'react'; const App = () => { const [num, setNum] = useState(0); // ๐Ÿ‘‡๏ธ Memoize function (doesn't get re-created every render) const incrementNum = useCallback(() => { setNum(prev => prev + 1); }, []); useEffect(() => { // ๐Ÿ‘‡๏ธ This only runs once incrementNum(); // ๐Ÿ‘‡๏ธ Include it in the dependencies array }, [incrementNum]); return ( <div> <h2>Number is {num}</h2> </div> ); }; export default App;

using use callback hook to memoize the function

The code for this article is available on GitHub

The useCallback hook takes an inline callback function and a dependencies array and returns a memoized version of the callback that only changes if one of the dependencies has changed.

Now that the incrementNum function is stable and doesn't change between renders, we can safely add it to the dependencies of the useEffect hook and it still runs only once.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev