Unable to dispatch redux action after receiving firebase DB data - firebase-realtime-database

I'm using react native app to get data from firebase database. The idea is to dispatch an action to initialise store.appState as soon as data is received from FirebaseDB. The issue is that dispatch is not fired when data is received. What am I missing?
I'm using redux-thunk middleware.
// database.js
import * as firebase from 'firebase'
const config = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "..."
}
const Database = firebase
.initializeApp(config)
.database()
.ref()
export default Database
// actions.js
import database from 'database'
const setInitDataFromFirebase = data => {
return ({
type: SET_DATA_INIT,
payload: {
data
}
})
}
export const loadAction = () => {
return dispatch => {
Database.once('value', snapshot=>{
console.log(snapshot.val()) // i get the log with correct data
dispatch(setInitDataFromFirebase(snapshot.val())) // this is not dispatched
})
}
}
// container.js
const View = (appState, loadData) => {
if (!appState) loadData() // appState is null initially
}
const matStateToProps (...) // passes appState
const mapDispatchToProps (...) // passes loadData
export default connect(mapStateToProps, mapDispatchToProps)(View)
}

I got this figured out. Turns out I made a very basic typo when I was importing redux-thunk. I should have done
import ReduxThunk from 'redux-thunk'
const store = createStore(
RootReducer,
applyMiddleware(ReduxThunk, logger)
)
What I had wrongly done was
import thunk from 'redux-thunk'
const store = createStore(
RootReducer,
applyMiddleware(thunk, logger)
)

Related

Angular / Ionic mobile app ios does not fetch from Firebase using angularfire

I am trying to test a little Ionic/Angular sample app on an iOS Emulator.
On the web, all the requests to firestore using angularfire work perfectly fine.
Somehow if I try to execute the same app on the emulator, it keeps loading for the response of the request (if it was a empty response it would say that no results could be retrieved).
What is going on? Do i need to set something specifically for the Emulator to work and perform requests to Firestore?
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { Capacitor } from '#capacitor/core';
import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
import { getAuth } from 'firebase/auth';
const firebaseApp = initializeApp({
apiKey: process.env.VUE_APP_FIREBASE_API_KEY,
authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.VUE_APP_FIREBASE_DATABASE_URL,
projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId:
process.env.VUE_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.VUE_APP_FIREBASE_APP_ID,
});
function whichAuth() {
let auth
if (Capacitor.isNativePlatform()) {
auth = initializeAuth(firebaseApp, {
persistence: indexedDBLocalPersistence
})
} else {
auth = getAuth()
}
return auth
}
export const auth = whichAuth()
const db = getFirestore();
export const auth = whichAuth();
export { firebaseApp, db };
Then in your component, cal your method like this await signInAnonymously(auth);. Don't forget to import the auth we exported at the top.
[Edit: updated with instructions Firebase JS SDK version 9 (modular)]
This error occurs because Firebase Auth incorrectly detects its environment as a normal browser environment and tries to load remote Google APIs, which results in the error you see in the console:
TypeError: undefined is not an object (evaluating 'gapi.iframes.getContext')
Fortunately, Firebase Auth already has logic to handle running in Cordova/Ionic apps, you just need to tell it which platform it's on.
For Firebase JS SDK version 9 (modular)
Simply import the Cordova Firebase Auth implementation:
import { getAuth } from 'firebase/auth';
For Firebase JS SDK <9 or the compatibility modules (auth/compat)
In capacitor.config set server: { iosScheme: "ionic" }:
// capacitor.config.json
{
"server": {
"iosScheme": "ionic"
}
}
There's a check in the auth/compat library here which, when it sees the URL scheme "ionic://", uses its Ionic/Cordova loading logic, and otherwise falls back to normal browser logic which fails with the error above.
Recent versions of Capacitor changed the URL scheme to "capacitor://" which fails this test but you can override it in your capacitor.config file (see the config option iosScheme).
(See also #alistairheath's comment here).
Been struggling a lot with this issue too but I managed to fix it. For those who need help here's my code.
You can delete all Firebase related imports from app.module.ts since this solution only uses Firebase.
The packages rxfire and #angular/fire can be removed from your package.json. The only dependency I have is "firebase": "^9.6.1".
I used observables for the getObject and list functions since that's what I'm used to and I didn't want to rewrite my original code.
import { Injectable } from '#angular/core';
import { Capacitor } from '#capacitor/core';
import { environment } from '#environment';
import { initializeApp } from 'firebase/app';
import { Auth, getAuth, indexedDBLocalPersistence, initializeAuth, signInWithCustomToken } from 'firebase/auth';
import { Database, getDatabase, onValue, orderByChild, query, ref } from 'firebase/database';
import { Observable, Observer, from } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class FirebaseService {
private readonly database: Database;
private readonly auth: Auth;
constructor() {
const firebaseApp = initializeApp(environment.firebase);
if (Capacitor.isNativePlatform()) {
initializeAuth(firebaseApp, {
persistence: indexedDBLocalPersistence
});
}
this.database = getDatabase(firebaseApp);
this.auth = getAuth(firebaseApp);
}
connectFirebase(firebaseToken) {
return from(signInWithCustomToken(this.auth, firebaseToken));
}
disconnectFirebase() {
return from(this.auth.signOut());
}
getObject<T>(path: string): Observable<T> {
return new Observable((observer: Observer<T>) => {
const dbRef = ref(this.database, path);
const listener = onValue(dbRef, snapshot => {
const data = snapshot.val();
observer.next(data);
});
return {
unsubscribe() {
listener();
}
};
});
}
public list<T>(path: string, orderChildBy?: string): Observable<Array<T>> {
return new Observable<Array<T>>((observer: Observer<Array<T>>) => {
const dbRef = ref(this.database, path);
const dbReference = !orderChildBy ? dbRef : query(dbRef, orderByChild(orderChildBy));
const listener = onValue(dbReference, snapshot => {
const data = Object.values<T>(snapshot.val() || {});
console.log(path, data);
observer.next(data);
});
return {
unsubscribe() {
listener();
}
};
});
}
}
For those who can't see the error message thrown by firebase try the following command in your Safari console to see the error.
window.location.reload()
The real problem: firebase-js-sdk on mobile iOS assumes google API (gapi) exists on the window, even when it isn't used.
I found a work around: Mock window.gapi before using firebase auth login:
window['gapi'] = {
load: (name: string) => Promise.resolve(),
iframes: {
getContext: () => {
return {
iframe: {
contentWindow: {
postMessage: (message: any) => {
console.log("gapi iframe message:", message);
}
}
}
}
}
}
} as any;

React-Native: Firebase Error: No Firebase App [DEFAULT] has been created - call Firebase App.initializeApp() (app/no-app) site:stackoverflow.com

I getting following error when try to read the data from firebase using redux.
React-Native: Firebase Error: No Firebase App [DEFAULT] has been created - call Firebase App.initializeApp() (app/no-app)
The connections with firebase works fine, cause I can create a new user and add new data to Firestore.
I have added my info.plist file
I have have config firebase in the app delegate
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
My redux Actions.js
import firebase from 'firebase/app';
import 'firebase/firestore';
import { USER_STATE_CHANGE, CLEAR_DATA, } from '../constans/index'
//fetch UserInfo from firebase
export function fetchUser() {
return (dispatch) => {
firebase
.firestore()
.collection("users")
.doc(firebase.auth().currentUser.uid)
.get()
.then((snapshot) => {
if (snapshot.exists) {
dispatch({ type: USER_STATE_CHANGE, currentUser: snapshot.data() });
} else {
console.log('does not exist');
}
});
};
}
So do anyone have a clue of what I should do. If I have added the "config" in Xcode, should I also do in App.js?
You need to initialize the firebase config file in your application like this:
const reactNativeFirebaseConfig = {
apiKey: ...,
authDomain: '...',
databaseURL: ...,
projectId: ...,
storageBucket: ...,
messagingSenderId: ...,
appId: ...,
};
if (firebase.apps.length === 0) {
firebase.initializeApp(reactNativeFirebaseConfig);
}
firebase.firestore();

How to mqtt publish on NestJS?

I am making mqtt client using NestJS
I used #MessagePattern to confirm the subscription. (#Ctx, #Payload information is also checked normally.)
By the way, mqtt client information is created in app.module
I tried to use MqttClient using #Inject in Controller
The following error occurs in client.push.
Help me
(The controller's client.publish does not work.)
[main.ts]
async function bootstrap() {
/*const app = await NestFactory.create(AppModule);
await app.listen(3000);*/
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,{
transport:Transport.MQTT,
options:{
url : 'serverIp',
username : 'name',
password : 'pwd',
port : 1883,
protocol : 'mqtt'
}
},
);
app.listen(() =>{
console.log('[Agent Server is Listening...]');
})
}
bootstrap();
[app.module.ts]
#Module({
imports: [
ClientsModule.register([
{
name: 'MQ_CLIENT',
transport: Transport.MQTT,
options: {
host:'serverIp',
port:1883,
//protocol:'mqtt',
username:'name',
password:'pwd'
}
},
]),
ConfigModule
],
controllers: [AppController, VcController],
providers: [AppService, VcService],
})
export class AppModule {}
[Controller]
#Controller('vc')
export class VcController {
constructor(
#Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger : LoggerService,
#Inject('MQ_CLIENT') private client : MqttClient
) {}
#MessagePattern('SomeTopic)
private tempFunction(#Ctx() context: MqttContext, #Payload() data){
this.client.publish('Publish TopicId', 'tttaaaaaa'); //The problem arises here
}
}
[Error Messgae]
TypeError: callback is not a function
at ClientMqtt.publish (C:\Wrok_Git\Demo\20201013_nestjsMqtt\mqtt-agent-02\node_modules\#nestjs\microservices\client\client-mqtt.js:104:13)
at VcController.vcTest (C:\Wrok_Git\Demo\20201013_nestjsMqtt\mqtt-agent-02\dist\controller\vc\vc.controller.js:40:21)
at C:\Wrok_Git\Demo\20201013_nestjsMqtt\mqtt-agent-02\node_modules\#nestjs\microservices\context\rpc-context-creator.js:44:33
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async C:\Wrok_Git\Demo\20201013_nestjsMqtt\mqtt-agent-02\node_modules\#nestjs\microservices\context\rpc-proxy.js:11:32
at async ServerMqtt.handleEvent (C:\Wrok_Git\Demo\20201013_nestjsMqtt\mqtt-agent-02\node_modules\#nestjs\microservices\server\server.js:61:32)
I did a little digging and came up with the following:
https://github.com/nestjs/nest/issues/6403
The gist of it, you need to call mqttClient.connect() beforehand, but you will not find that function in the interface for it.
This works for me -
constructor(#Inject('MQ_CLIENT') private client: ClientProxy) {
client.connect();
}
#MessagePattern('SomeTopic')
private tempFunction(#Ctx() context: MqttContext, #Payload() data) {
this.client.emit('help', 'data');
}
The code of question is all OK.
Only replace the line
this.client.publish('Publish TopicId', 'tttaaaaaa');
with
this.client.emit('Publish TopicId', 'tttaaaaaa')

Is there any way to track an event using firebase in electron + react

I want to ask about how to send an event using firebase & electron.js. A friend of mine has a problem when using firebase analytics and electron that it seems the electron doesn't send any event to the debugger console. When I see the network it seems the function doesn't send anything but the text successfully go in console. can someone help me to figure it? any workaround way will do, since he said he try to implement the solution in this topic
firebase-analytics-log-event-not-working-in-production-build-of-electron
electron-google-analytics
this is the error I got when Try to use A solution in Point 2
For information, my friend used this for the boiler plate electron-react-boilerplate
The solution above still failed. Can someone help me to solve this?
EDIT 1:
As you can see in the image above, the first image is my friend's code when you run it, it will give a very basic example like in the image 2 with a button to send an event.
ah just for information He used this firebase package :
https://www.npmjs.com/package/firebase
You can intercept HTTP protocol and handle your static content though the provided methods, it would allow you to use http:// protocol for the content URLs. What should make Firebase Analytics work as provided in the first question.
References
Protocol interception documentation.
Example
This is an example of how you can serve local app as loaded by HTTP protocol and simulate regular browser work to use http protocol with bundled web application. This will allow you to add Firebase Analytics. It supports poorly HTTP data upload, but you can do it on your own depending on the goals.
index.js
const {app, BrowserWindow, protocol} = require('electron')
const http = require('http')
const {createReadStream, promises: fs} = require('fs')
const path = require('path')
const {PassThrough} = require('stream')
const mime = require('mime')
const MY_HOST = 'somehostname.example'
app.whenReady()
.then(async () => {
await protocol.interceptStreamProtocol('http', (request, callback) => {
const url = new URL(request.url)
const {hostname} = url
const isLocal = hostname === MY_HOST
if (isLocal) {
serveLocalSite({...request, url}, callback)
}
else {
serveRegularSite({...request, url}, callback)
}
})
const win = new BrowserWindow()
win.loadURL(`http://${MY_HOST}/index.html`)
})
.catch((error) => {
console.error(error)
app.exit(1)
})
async function serveLocalSite(request, callback) {
try {
const {pathname} = request.url
const filepath = path.join(__dirname, path.resolve('/', pathname))
const stat = await fs.stat(filepath)
if (stat.isFile() !== true) {
throw new Error('Not a file')
}
callback(
createResponse(
200,
{
'content-type': mime.getType(path.extname(pathname)),
'content-length': stat.size,
},
createReadStream(filepath)
)
)
}
catch (err) {
callback(
errorResponse(err)
)
}
}
function serveRegularSite(request, callback) {
try {
console.log(request)
const req = http.request({
url: request.url,
host: request.url.host,
port: request.url.port,
method: request.method,
headers: request.headers,
})
if (req.uploadData) {
req.write(request.uploadData.bytes)
}
req.on('error', (error) => {
callback(
errorResponse(error)
)
})
req.on('response', (res) => {
console.log(res.statusCode, res.headers)
callback(
createResponse(
res.statusCode,
res.headers,
res,
)
)
})
req.end()
}
catch (err) {
callback(
errorResponse(err)
)
}
}
function toStream(body) {
const stream = new PassThrough()
stream.write(body)
stream.end()
return stream
}
function errorResponse(error) {
return createResponse(
500,
{
'content-type': 'text/plain;charset=utf8',
},
error.stack
)
}
function createResponse(statusCode, headers, body) {
if ('content-length' in headers === false) {
headers['content-length'] = Buffer.byteLength(body)
}
return {
statusCode,
headers,
data: typeof body === 'object' ? body : toStream(body),
}
}
MY_HOST is any non-existent host (like something.example) or host that is controlled by admin (in my case it could be electron-app.rumk.in). This host will serve as replacement for localhost.
index.html
<html>
<body>
Hello
</body>
</html>

Flutter-Firebase phone Auth always returns Token mismatch on iOS

I'm trying to use phone Authentication and it's working as expected on Android, but on iOS I always get Token mismatch and don't receive a code.
other Firebase services like cloud firestore and email Auth are working fine on iOS.
I made sure of the following:
-APN key is added in Firebase
-Google Services file is updated
-Background Modes and Push Notification capabilities are on
the error message is from PhoneVerificationFailed
Future<void> _verifyPhoneNumber() async {
setState(() {
_message = '';
});
final PhoneVerificationCompleted verificationCompleted =
(AuthCredential phoneAuthCredential) async {
await _auth.signInWithCredential(phoneAuthCredential);
setState(() {
_message = 'Received phone auth credential: $phoneAuthCredential';
});
};
final PhoneVerificationFailed verificationFailed =
(AuthException authException) {
setState(() {
_message = '********************\n\n'
'Phone number verification failed. Code: ${authException.code}.'
'\n Message: ${authException.message}'
'\n\n********************';
});
};
final PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async {
_verificationId = verificationId;
setState(() {
_message = 'waiting for code';
//waitingCode = true;
});
};
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
(String verificationId) {
_verificationId = verificationId;
};
try {
await _auth.verifyPhoneNumber(
phoneNumber: number,
timeout: const Duration(seconds: 30),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
} catch (e) {
print('Error is $e');
}
}
and I'm getting these messages from log
Userinfo {
"com.google.firebase.auth" = {
warning = "This fake notification should be forwarded to Firebase Auth.";
};
}
UserDate : {
"com.google.firebase.auth" = {
warning = "This fake notification should be forwarded to Firebase Auth.";
};
}
UserDate Json : {
"com.google.firebase.auth" : {
"warning" : "This fake notification should be forwarded to Firebase Auth."
}
}
flutter:
TRUE
flutter: Call Back {
"com.google.firebase.auth" : {
"warning" : "This fake notification should be forwarded to Firebase Auth."
}
}
I understand it's too late in answering this. But I also faced the same error recently. I fixed the issue on iOS. Your entire configuration must be valid. There are two settings you need to make.
Remove any method swizzling variable from GoogleService-info.plist
i.e. remove FirebaseAppDelegateProxyEnabled property from plist
In AppDelegate.swift, override this method and set the following
func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
Messaging.messaging().apnsToken = deviceToken
}
It is mentioned at https://firebase.google.com/docs/cloud-messaging/ios/client#token-swizzle-disabled
I am using firebase_messaging: ^6.0.16 and the above settings worked
Changing the Firebase Auth version from 0.14.0 to
firebase_auth:
git:
url: https://github.com/collinjackson/plugins.git
ref: 441417c2fed0ff26bf84a49ab2c5ffd2aa5487de
path: packages/firebase_auth
fixed my issue.
see https://github.com/flutter/flutter/issues/35267 for more details

Resources