0

I want to run a callback when a component mounts, but not on each render. Using useEffect and an empty dependency array created warnings. I read on a different thread which I now can't find that this can be achieved by creating a custom hook:

import {useRef} from "react";

const useInitialise = (callback) => {
    //TODO this is running every render!
    const runOnce = useRef(false);
    if (!runOnce.current) {
        callback();
        runOnce.current = true;
    }
}

export default useInitialise;

Usage:

useInitialise(() => {
    //callback
});

This is instead of using:

useEffect(() => {
        //callback
    }, []);

As this generates warnings. I understand that the hook will be called on each render, but why is the runOnce.current not preventing the callback being run twice?

Laurence Summers
  • 201
  • 1
  • 3
  • 14

1 Answers1

0

Found the thread!

I should use a state to track mounted/unmounted, then useEffect to call the callback only if either mounted or callback change:

import {useEffect, useState} from "react";

const useInitialise = (callback) => {
    const [mounted, setMounted] = useState(false)
    useEffect(() => {
        if (!mounted) {
            setMounted(true);
            callback();
        }
    }, [mounted, callback]);
}

export default useInitialise;
Laurence Summers
  • 201
  • 1
  • 3
  • 14
  • There is nothing wrong with using a `useEffect` with empty deps array. In fact I would prefer that over this stateful approach – Bugbeeb Jan 17 '22 at 01:51
  • Then why is there a warning about it? – Laurence Summers Jan 18 '22 at 08:24
  • what warnings are you seeing? – Bugbeeb Jan 18 '22 at 17:04
  • If the callback is “getEntries” for example - it’s not included in the array as 1. Doesn’t change and 2. That causes an infinite loop. I understand the warning is because there’s a variable in the useEffect but not array, so the aim is to have a way of executing code on first mount only without warnings React Hook useEffect has a missing dependency: 'getEntries'. Either include it or remove the dependency array react-hooks/exhaustive-deps – Laurence Summers Jan 21 '22 at 09:39
  • Did you wrap the callback in a `useCallback` to memoize it? Then it would be safe to include in the dependencies array – Bugbeeb Jan 21 '22 at 15:52