[javascript] How to call loading function with React useEffect only once

The useEffect React hook will run the passed in function on every change. This can be optimized to let it call only when the desired properties change.

What if I want to call an initialization function from componentDidMount and not call it again on changes? Let's say I want to load an entity, but the loading function doesn't need any data from the component. How can we make this using the useEffect hook?

class MyComponent extends React.PureComponent {
    componentDidMount() {
        loadDataOnlyOnce();
    }
    render() { ... }
}

With hooks this could look like this:

function MyComponent() {
    useEffect(() => {
        loadDataOnlyOnce(); // this will fire on every change :(
    }, [...???]);
    return (...);
}

This question is related to javascript reactjs react-hooks

The answer is


If you only want to run the function given to useEffect after the initial render, you can give it an empty array as second argument.

function MyComponent() {
  useEffect(() => {
    loadDataOnlyOnce();
  }, []);

  return <div> {/* ... */} </div>;
}

TL;DR

useEffect(yourCallback, []) - will trigger the callback only after the first render.

Detailed explanation

useEffect runs by default after every render of the component (thus causing an effect).

When placing useEffect in your component you tell React you want to run the callback as an effect. React will run the effect after rendering and after performing the DOM updates.

If you pass only a callback - the callback will run after each render.

If passing a second argument (array), React will run the callback after the first render and every time one of the elements in the array is changed. for example when placing useEffect(() => console.log('hello'), [someVar, someOtherVar]) - the callback will run after the first render and after any render that one of someVar or someOtherVar are changed.

By passing the second argument an empty array, React will compare after each render the array and will see nothing was changed, thus calling the callback only after the first render.


useMountEffect hook

Running a function only once after component mounts is such a common pattern that it justifies a hook of it's own that hides implementation details.

const useMountEffect = (fun) => useEffect(fun, [])

Use it in any functional component.

function MyComponent() {
    useMountEffect(function) // function will run only once after it has mounted. 
    return <div>...</div>;
}

About the useMountEffect hook

When using useEffect with a second array argument, React will run the callback after mounting (initial render) and after values in the array have changed. Since we pass an empty array, it will run only after mounting.


Pass an empty array as the second argument to useEffect. This effectively tells React, quoting the docs:

This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.

Here's a snippet which you can run to show that it works:

_x000D_
_x000D_
function App() {_x000D_
  const [user, setUser] = React.useState(null);_x000D_
_x000D_
  React.useEffect(() => {_x000D_
    fetch('https://randomuser.me/api/')_x000D_
      .then(results => results.json())_x000D_
      .then(data => {_x000D_
        setUser(data.results[0]);_x000D_
      });_x000D_
  }, []); // Pass empty array to only run once on mount._x000D_
  _x000D_
  return <div>_x000D_
    {user ? user.name.first : 'Loading...'}_x000D_
  </div>;_x000D_
}_x000D_
_x000D_
ReactDOM.render(<App/>, document.getElementById('app'));
_x000D_
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>_x000D_
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>_x000D_
_x000D_
<div id="app"></div>
_x000D_
_x000D_
_x000D_


I like to define a mount function, it tricks EsLint in the same way useMount does and I find it more self-explanatory.

const mount = () => {
  console.log('mounted')
  // ...

  const unmount = () => {
    console.log('unmounted')
    // ...
  }
  return unmount
}
useEffect(mount, [])


leave the dependency array blank . hope this will help you understand better.

   useEffect(() => {
      doSomething()
    }, []) 

empty dependency array runs Only Once, on Mount

useEffect(() => {
  doSomething(value)
}, [value])  

pass value as a dependency. if dependencies has changed since the last time, the effect will run again.

useEffect(() => {
  doSomething(value)
})  

no dependency. This gets called after every render.


we developed a module on GitHub that has hooks for fetching data so you can use it like this for your purpose:

import { useFetching } from "react-concurrent";

const app = () => {
  const { data, isLoading, error , refetch } = useFetching(() =>
    fetch("http://example.com"),
  );
};

You can fork that out, but any PRs are welcome. https://github.com/hosseinmd/react-concurrent#react-concurrent


function useOnceCall(cb, condition = true) {
  const isCalledRef = React.useRef(false);

  React.useEffect(() => {
    if (condition && !isCalledRef.current) {
      isCalledRef.current = true;
      cb();
    }
  }, [cb, condition]);
}

and use it.

useOnceCall(()=>{
  console.log('called');
})

or

useOnceCall(()=>{
  console.log('isLoading');
},isLoading);

Questions with javascript tag:

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax Drag and drop menuitems Is it possible to execute multiple _addItem calls asynchronously using Google Analytics? DevTools failed to load SourceMap: Could not load content for chrome-extension TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app What does 'x packages are looking for funding' mean when running `npm install`? SyntaxError: Cannot use import statement outside a module SameSite warning Chrome 77 "Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6 Why powershell does not run Angular commands? Typescript: No index signature with a parameter of type 'string' was found on type '{ "A": string; } Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop Push method in React Hooks (useState)? JS file gets a net::ERR_ABORTED 404 (Not Found) React Hooks useState() with Object useState set method not reflecting change immediately Can't perform a React state update on an unmounted component UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block Can I set state inside a useEffect hook internal/modules/cjs/loader.js:582 throw err How to post query parameters with Axios? How to use componentWillMount() in React Hooks? React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory in ionic 3 How can I force component to re-render with hooks in React? What is useState() in React? How to call loading function with React useEffect only once Objects are not valid as a React child. If you meant to render a collection of children, use an array instead How to reload current page? Center content vertically on Vuetify Getting all documents from one collection in Firestore ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment How can I add raw data body to an axios request? Sort Array of object by object field in Angular 6 Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Axios Delete request with body and headers? Enable CORS in fetch api Vue.js get selected option on @change Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) Angular 6: How to set response type as text while making http call

Questions with reactjs tag:

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop react hooks useEffect() cleanup for only componentWillUnmount? How to use callback with useState hook in react Push method in React Hooks (useState)? React Hooks useState() with Object useState set method not reflecting change immediately Can't perform a React state update on an unmounted component React hooks useState Array Can I set state inside a useEffect hook TypeScript and React - children type? Why do I keep getting Delete 'cr' [prettier/prettier]? How to use componentWillMount() in React Hooks? How to compare oldValues and newValues on React Hooks useEffect? React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing Receiving "Attempted import error:" in react app How can I force component to re-render with hooks in React? What is useState() in React? How to call loading function with React useEffect only once expected assignment or function call: no-unused-expressions ReactJS Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Support for the experimental syntax 'classProperties' isn't currently enabled How can I add raw data body to an axios request? Axios Delete request with body and headers? Enable CORS in fetch api Axios having CORS issue How to center a component in Material-UI and make it responsive? What exactly is the 'react-scripts start' command? how to download file in react js react button onClick redirect page Local package.json exists, but node_modules missing Upgrading React version and it's dependencies by reading package.json What is {this.props.children} and when you should use it? How to use lifecycle method getDerivedStateFromProps as opposed to componentWillReceiveProps Adding an .env file to React Project React : difference between <Route exact path="/" /> and <Route path="/" /> You should not use <Link> outside a <Router> ReactJS: Maximum update depth exceeded error Functions are not valid as a React child. This may happen if you return a Component instead of from render where is create-react-app webpack config and files? React Native: JAVA_HOME is not set and no 'java' command could be found in your PATH

Questions with react-hooks tag:

Invalid hook call. Hooks can only be called inside of the body of a function component React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? react hooks useEffect() cleanup for only componentWillUnmount? How to use callback with useState hook in react Push method in React Hooks (useState)? React Hooks useState() with Object useState set method not reflecting change immediately React hooks useState Array Can I set state inside a useEffect hook How to use componentWillMount() in React Hooks? How to compare oldValues and newValues on React Hooks useEffect? React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing How can I force component to re-render with hooks in React? What is useState() in React? How to call loading function with React useEffect only once