TypeError: e не является функцией.
Ошибка возникает при размонтировании компонента, когда React пытается вызвать возвращенную функцию очистки. Консоль показывает, что прослушиватель запускается нормально, но затем, когда компонент размонтируется, отображается ошибка.
Я использую прослушиватели реального времени Firebase Firestore для отображения обновлений данных в реальном времени в моем приложении. Проблема заключается в том, как плагин Firebase Capacitor обрабатывает функцию очистки onSnapshot. В React вы должны возвращать функцию очистки из useEffect Вот так:
useEffect(() => {
const unsubscribe = onSnapshot(query, (snapshot) => {
// handle data
});
return () => unsubscribe(); // cleanup when component unmounts
}, []);
Это отлично работает с обычным веб-SDK Firebase. Но плагин Capacitor Firebase (@capacitor-firebase/firestore) не возвращает функцию — он возвращает обещание, которое в конечном итоге дает вам идентификатор обратного вызова. Я пытался обернуть это так, чтобы React принял это, но что-то сломалось в процессе минификации.
Мой код оболочки
Вот что я пытался:
import { FirebaseFirestore } from '@capacitor-firebase/firestore';
import { onSnapshot as webOnSnapshot } from 'firebase/firestore';
export function onSnapshot(queryRef, callback, errorCallback) {
if (isCapacitor()) {
// This is where things get tricky...
const unsubscribeHolder = { callbackId: null, isUnsubscribed: false };
// Start the listener (this returns a Promise)
FirebaseFirestore.addCollectionSnapshotListener(
{
reference: queryRef._path,
compositeFilter: queryRef._compositeFilter
},
(event) => {
if (!unsubscribeHolder.isUnsubscribed) {
callback(processSnapshot(event));
}
}
).then(listener => {
// Store the callback ID for cleanup
unsubscribeHolder.callbackId = listener.callbackId;
}).catch(errorCallback);
// Return a function that uses the holder
return function() {
unsubscribeHolder.isUnsubscribed = true;
if (unsubscribeHolder.callbackId) {
FirebaseFirestore.removeSnapshotListener({
callbackId: unsubscribeHolder.callbackId
});
}
};
}
// Browser version works fine
return webOnSnapshot(queryRef, callback, errorCallback);
}
При разработке и производстве в режиме браузера все работает отлично. Но на iOS в режиме разработки: Listener запускается, но возникают ошибки очистки, а на рабочей версии iOS он полностью ломается с загадочной ошибкой TypeError: e не является ошибкой функции.
Ошибка возникает, когда компонент размонтируется и React пытается вызвать функцию очистки. Это похоже на то, что минификатор React делает что-то с кодом, который разрушает мост между обещанием и функцией, который я пытаюсь создать.
Я пробовал:
- Синхронно возвращать функцию отписки (все еще прерывается после минификации)
- Проверка typeof unsubscribe === 'function' перед ее вызовом (проверка проходит, но он по-прежнему ошибается!)
- Несколько вариантов шаблона держателя
- Различные оболочки обещаний
Мои вопросы:
- Кто-нибудь действительно получил прослушиватели Firestore в реальном времени, работающие с Capacitor + React в производстве?
- Есть ли правильный способ соединить асинхронный API Capacitor с Шаблон синхронной очистки React?
Среда:
{
"@capacitor-firebase/firestore": "^7.3.1",
"@capacitor/core": "^7.4.3",
"firebase": "^11.2.0",
"react": "^19.0.0",
"react-scripts": "5.0.1"
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... -useeffect
Мобильная версия