ReactJS: how to call useEffect hook only once to fetch API data

If I understand correctly, you want to mimic the "on component mounted" behaviour of regular class based react components via useEffect(), so that the effect callback only fires once on the first render.

To achieve that behaviour, you can pass an empty array to the second argument of useEffect() like so:

useEffect(() => {
  loadMessages();
}, []); /* <-- add this */

The second array argument allows you to specify which prop variables trigger the useEffect() callback (if any) when their value(s) change.

By passing an empty array, this means that useEffect() won't be triggered by any changes to input prop variables and will in turn only ever be called once, during the first render.

For more information on this second argument, see this documentation and this documentation


useEffect() is a react hook for functional components which covers the functionality of the lifecycle hooks of the class components. useEffect() combines componentDidMount(), componentDidUpdate() and componentWillUnmount() of the class components, which means it will execute when the component is mounted, when the state of the component changes and when the component is unmounted from the DOM.

Check below example,

useEffect(() => {
   setTimeout(() => {
      alert("data saved");
    }, 1000);
});

Above code/alert is executed when the component is mounted/initial render, when state of the component changes and when component is unmounted from the DOM.

To make the above code run less often we can pass an array of values as the second argument, as the dependencies for that effect. If one of the dependencies change the effect will run again.

Consider we have persons array passed into the props of the functional component and we want the alert to execute only when the persons array change.

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, [props.persons]);

This will execute the code during initial render and when props.persons changes.

So to execute the code only during initial render/component mount you can pass an empty array which means no dependencies specified when the effect should execute. Hence run during initial render and when the component is unmounted.

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, []);

You can modify your useEffect() hook as below to call it only once to fetch API data,

useEffect(() => {
    loadMessages();
  }, []);