То, как я читаю ваш вышеупомянутый компонент, создает впечатление, что вы определили пользовательский хук для получения данных из firebase.
Итак, во-первых, я бы переименовал его в FbData и воспринимал его как пользовательский хук, чтобы вы могли использовать плагин ESLint для хуков и убедиться, что вы следуете правила хуков .
То, как вы это сделали выше, если это функция внутри компонента, ваша функция будет срабатывать при каждом рендеринге, поэтому описываемое вами поведение - то, что я ожидал,
В зависимости от того, насколько дорогим является ваш запрос / как часто этот компонент обрабатывается, это может быть тем, что вам нужно, поскольку вы, вероятно, не хотите возвращать устаревшие данные вашему компоненту. Однако, если вы чувствуете, что ответ из БД должен быть кэширован, и у вас есть логика для аннулирования этих данных, вы можете попробовать что-то вроде этого:
import { useEffect, useRef } from 'react';
const useFbData = invalidationFlag => {
const data = useRef(null);
useEffect(() => {
if (!data.current || invalidationFlag) {
firebase.database().ref('Data').on('value', (snapshot) => {
data.current = snapshot.val();
});
}
}, [invalidationFlag]);
return data.current;
};
export default useFbData;
Таким образом, при первоначальном запуске и каждый раз, когда выизменил значение invalidationFlag, ваш эффект внутри хука useFbData запустится. При условии, что вы следите за invalidationFlag и устанавливаете его как требуется, это может сработать для вас.
Причина, по которой я использовал здесь ref вместо state, заключается в том, что ловушка эффекта не принимает данные вмассив зависимостей (который может привести к его бесконечному циклу, если мы используем состояние).
Это сохранит результат ответа db между каждым вызовом и предотвратит повторный вызов до тех пор, пока вы не сделаете недействительным. Помните, что это будет означать, что данные, которые вы используете, устарели, пока вы не сделаете их недействительными.