Во-первых, самое главное, все значения, которые используете в React, должны быть обернуты, т.к. нельзя контролировать в полной мере обновление компонента, особенно если он будет обернут в дерево (находиться внутри других компонент). Т.е. используйте значения только из useState, переданных параметров props. useMemo не сможет распознать иных зависимостей.
Во-вторых, useEffect должен использовать зависимости, чтобы не вызывался каждый раз. Если Вам нужно выполнение эффекта только при инициализации компонента, укажите useEffect(callback, []). useEffect без зависимостей практически бесполезен (и есть трюки, чтобы довести до однократного выполнения с помощью useRef).
В-третьих, если Вам нужно значение вне компонента, как хранилище, используйте прокси (передача значения сверху-вниз из родительских компонент в виде props), например, или другие инструменты (Redux, MobX).
Например,
import React from 'react';
function App(props) {
return <a onClick={() => props.addIdCounter()}>{ props.idCounter }</a>
}
function RootComponent () {
const [idCounter, setIdCounter] = React.useEffect(0);
const addIdCounter = () => setIdCounter(idCounter + 1);
return <App addIdCounter={addIdCounter} idCounter={idCounter} />;
}