I am creating an app with TypeScript + Firebase. I've followed this website to set it up: https://rnfirebase.io. After I finished with authentication I wanted to get a value from the real time database. However making the request doesn't resolve. I've also put it in the await version however that didn't resolve either.
import React, { useEffect } from "react";
import { Text } from "react-native";
import { firebase } from "#react-native-firebase/database";
import { REALTIME_DATABASE_ENV } from "react-native-dotenv";
const TestPage = () => {
useEffect(() => {
const reference = firebase
.app()
.database(REALTIME_DATABASE_ENV)
.ref("particularities/")
.once("value")
.then((snapshot) => {
console.log(`snapshot: ${snapshot.val()}`);
//expected result:
// {
// sickness: {
// label: "Sickness",
// },
// allergic: {
// label: "Allergic",
// },
// };
})
.catch((e: unknown) => {
console.log(`catch: ${e}`);
});
}, []);
return (
<Text>Test page</Text>
);
};
export default TestPage;
The rules that are applied to the real time database:
{
"rules": {
".read": false,
".write": false,
// ...
"particularities": {
".read": true,
".write": true,
},
}
}
Thing we found: logging out of the app does resolve all the requests made. Testing while logged in and all rules set to public gives the same result as before with the promise not resolving
As per the documentation here is how you can read the data once.
https://rnfirebase.io/database/usage#one-time-read
You don't need to pass database ref other than an 'us-central1'
import database from '#react-native-firebase/database';
database()
.ref('particularities/')
.once('value')
.then(snapshot => {
console.log('Data: ', snapshot.val());
})
.catch((e: unknown) => {
console.log(`catch: ${e}`);
});
Related
Push notification is not receiving in react native android device at first it was working but suddenly don't know what happenend..its not working..can anyone help me with this first file where i have generated the device token and second file for foreground
//notificationServices
import messaging from '#react-native-firebase/messaging';
import AsyncStorage from '#react-native-async-storage/async-storage';
export async function requestUserPermission() {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
console.log('Authorization status:', authStatus);
getFcmToken();
}
}
const getFcmToken = async () => {
let fcmToken = await AsyncStorage.getItem("fcmToken");
console.log(fcmToken,'token old');
if(!fcmToken) {
try {
const fcmToken = await messaging().getToken();
if(fcmToken){
console.log(fcmToken,'the new token');
await AsyncStorage.setItem("fcmToken",fcmToken)
}
}
catch (error) {
console.log(error,'error in fcmtoken');
}
}
}
export const notificationListener = async () => {
messaging().onNotificationOpenedApp(remoteMessage => {
console.log(
'Notification caused app to open from background state:',
remoteMessage.notification,
);
});
messaging()
.getInitialNotification()
.then(remoteMessage => {
if (remoteMessage) {
console.log(
'Notification caused app to open from quit state:',
remoteMessage.notification,
);
}
});
}
//foregroundhandler.js
import PushNotification, {Importance} from 'react-native-push-notification';
import messaging from '#react-native-firebase/messaging'
import React , {useEffect} from 'react'
const ForegroundHandler = () => {
const channel = new firebase.notifications.Android.Channel('test-channel', 'Test
Channel', firebase.notifications.Android.Importance.Max)
.setDescription('My apps test channel');
// Create the channel
firebase.notifications().android.createChannel(channel);
useEffect(() => {
const unsubscribe = messaging().onMessage((remoteMessage) => {
console.log("handle in foreground" , remoteMessage)
const {notification , messageId} = remoteMessage
PushNotification.createChannel(
{
channelId: "channel_id_1", // (required)
channelName: "My channel", // (required)
playSound: false, // (optional) default: true
soundName: "default", // (optional) See `soundName` parameter of
`localNotification` function
importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
},
(channelId) => console.log(`createChannel returned '${channelId}'`) // (optional) callback returns whether the channel was created, false means it already existed.
);
PushNotification.localNotification({
channelId:'channel_id_1',
id:messageId,
body:'android body',
title :'android notif title',
soundName:'default',
vibrate:true,
playSound:true
})
})
return unsubscribe
}, [])
return null
}
export default ForegroundHandler
Working with older React.
How to correctly get data from an endpoint?
It complains about state
I am a React newbie. Looked on Tutorials but it seems developer who did this code used some other convention in creating Classes/Components.
Tried this:
import React from "react"
import Utils from "utils"
import {A, makeUrl, redirectTo} from "routing"
import Settings from "settings"
import ProjectApi from "api/project"
import FlashMessagesService from "flash_messages"
var ProjectHeader = React.createClass({
displayName: 'ProjectHeader',
state = {
project: [],
},
componentDidMount() {
// need to make the initial call to getData() to populate
// data right away
// Now we need to make it run at a specified interval
setInterval(this.refresh, 1000); // runs every 5 seconds.
},
refresh : function(){
var props = this.props
var providers = Settings.providers['project.header.info'] || []
providers
.filter(function(provider) {
return provider.component.isApplicable(props.project)
})
.forEach(function (provider) {
projectInfo.push(<provider.component project={props.project} {...props}/>)
})
fetch('/api/v1/project/'+props.project.pk)
.then(response => response.json())
.then(data => {
this.setState({ project: data.project });
});
if (this.state.project.analysis_status == 'succeeded') {
window.location.reload();
}
},
Thanks,
There was a typo in the state line (line 11) which should have been state: { rather than state = {. Another potential complaint it might have had is that during runtime after the component was unmounted, the interval would've continued firing, so I added a clearInterval in componentWillUnmount.
import Utils from 'utils';
import { A, makeUrl, redirectTo } from 'routing';
import Settings from 'settings';
import ProjectApi from 'api/project';
import FlashMessagesService from 'flash_messages';
var ProjectHeader = React.createClass({
displayName: 'ProjectHeader',
intervalId: null,
state: {
project: [],
},
componentDidMount() {
// need to make the initial call to getData() to populate
// data right away
// Now we need to make it run at a specified interval
this.intervalId = setInterval(this.refresh, 1000); // runs every 5 seconds.
},
componentWillUnmount(){
clearInterval(this.intervalId);
},
refresh: function () {
var props = this.props;
var providers = Settings.providers['project.header.info'] || [];
providers
.filter(function (provider) {
return provider.component.isApplicable(props.project);
})
.forEach(function (provider) {
projectInfo.push(
<provider.component project={props.project} {...props} />
);
});
fetch('/api/v1/project/' + props.project.pk)
.then((response) => response.json())
.then((data) => {
this.setState({ project: data.project });
});
console.log(hits);
if (hits.analysis_status == 'succeeded') {
window.location.reload();
}
},
I am integrating Paypal express checkout with gatsby(reactjs) it's perfectly working fine with sandbox accounts but not in production. It gives me the following error
My code is
import React, { useState } from "react"
import PaypalExpressBtn from "react-paypal-express-checkout"
import notify from "../functions/notify"
import Api from "../functions/API"
import fbTrack from "../functions/fbTrack"
const client = {
sandbox: "sanbox_key",
production: "prod_key",
}
export default ({ plan, setUserData, setBillingHistory, setUserContact }) => {
const onSuccess = (payment) => {
const data = {
payment,
plan,
}
notify("The payment was succeeded!")
try {
fbTrack("track", "Purchase", plan.price)
} catch (e) {
// do nothing
}
// Sending the res call
Api.fetch("post", "make-payment-paypal", data).then(() => {
Api.fetch()
.then(user => {
setUserData(user)
})
Api.fetch("get", "get-contact")
.then(contact => {
setUserContact(contact)
})
Api.fetch("get", "get-billing-history")
.then(billing => {
setBillingHistory(billing)
})
}).catch(e => console.log(e))
}
const onCancel = (data) => {
notify("The payment was cancelled", "danger")
}
const onError = (err) => {
notify("Error occurred. Please retry.", "danger")
}
return <PaypalExpressBtn env={"production"} client={client} currency={plan.currency_code} total={plan.price} onError={onError}
onSuccess={onSuccess} onCancel={onCancel}/>
}
Response from network tab for /execute endpoint that gives 400
{
"ack": "contingency",
"contingency": "INSTRUMENT_DECLINED",
"meta": {
"calc": "e8cc408a47d1f",
"rlog": "rZJvnqaaQhLn%2FnmWT8cSUueWscmrtUHe5Y1Bd%2FeqyvyOTq66rSXAcvMRdZesXq1O38dITQfoakLPn1nG4pMu0qURH%2Be5YB%2B4_1709bb5bb49"
},
"server": "2mEzKB-B1lh9-OtP-2sBI96A-5Xu_ZnMt0Rz1fJ2a4n4noKlAHLadCNfrWklmy5YUKipx6UR0bGzcI9u9Q-a4b1v4LHPM9g6W4a6WmXYuh9wqhRDdbsHbYSzXX8ucZU3a4Xp-wZrSy6qYgnEZoDKzjuz_fjiBvxhxD2fNlGbF5tm_h_xd-G9FaYynEq4jwg1MYcCAXMgLLsxc2J81gNfe01GF7FRInwK5mbgWxtwed9fOwRRfBycXsn_diFRBuIJR7UEXAfmeZYIzkBATQbYfm"
}
{
"ack": "contingency",
"contingency": "INSTRUMENT_DECLINED",
"meta": {
"calc": "e8cc408a47d1f",
"rlog": "rZJvnqaaQhLn%2FnmWT8cSUueWscmrtUHe5Y1Bd%2FeqyvyOTq66rSXAcvMRdZesXq1O38dITQfoakLPn1nG4pMu0qURH%2Be5YB%2B4_1709bb5bb49"
},
"server": "2mEzKB-B1lh9-OtP-2sBI96A-5Xu_ZnMt0Rz1fJ2a4n4noKlAHLadCNfrWklmy5YUKipx6UR0bGzcI9u9Q-a4b1v4LHPM9g6W4a6WmXYuh9wqhRDdbsHbYSzXX8ucZU3a4Xp-wZrSy6qYgnEZoDKzjuz_fjiBvxhxD2fNlGbF5tm_h_xd-G9FaYynEq4jwg1MYcCAXMgLLsxc2J81gNfe01GF7FRInwK5mbgWxtwed9fOwRRfBycXsn_diFRBuIJR7UEXAfmeZYIzkBATQbYfm"
}
This means the card was declined.
So I am trying to use cognito to manage authentication in my react application, with the identity provider being SAML. This is working very smoothly in Chrome and Firefox, but not in IE 11. Here is I set up my Auth:
import { Component } from 'react';
import { connect } from 'react-redux';
import { CognitoAuth } from 'amazon-cognito-auth-js';
import { signIn, signOutSuccess } from '../store/auth';
import { setupAxios } from '../axios';
import {
AWS_COGNITO_CLIENT_ID,
AWS_COGNITO_USER_POOL_ID,
AWS_COGNITO_REDIRECT_SIGN_IN,
AWS_COGNITO_REDIRECT_SIGN_OUT,
AWS_COGNITO_APP_WEB_DOMAIN
} from '../env';
const cognitoSetup = props => {
//as per documentation
const authData = {
ClientId: AWS_COGNITO_CLIENT_ID,
TokenScopesArray: ['email', 'openid', 'profile'],
RedirectUriSignIn: AWS_COGNITO_REDIRECT_SIGN_IN,
RedirectUriSignOut: AWS_COGNITO_REDIRECT_SIGN_OUT,
AppWebDomain: AWS_COGNITO_APP_WEB_DOMAIN,
IdentityProvider: 'SAML',
UserPoolId: AWS_COGNITO_USER_POOL_ID
};
const auth = new CognitoAuth(authData);
auth.useCodeGrantFlow(); //getting the refresh token
auth.userhandler = {
onSuccess: result => {
const { profile, name, family_name, email } = result.idToken.payload;
//passes role to store for use in the rest of the app
const username = result.idToken.payload.identities[0].userId;
const fullName = `${name} ${family_name}`;
props.signIn({ username, profile, fullName, email });
},
onFailure: function(err) {
console.error(err);
throw err;
}
};
return auth;
};
export class AuthService extends Component {
constructor(props) {
super(props);
this.authService = cognitoSetup(this.props);
//passes the auth to axios to check for token on request
setupAxios(this.authService);
}
componentDidMount() {
const curUrl = window.location.href;
if (curUrl.includes('?code=')) {
this.authService.parseCognitoWebResponse(curUrl);
} else if (!curUrl.includes('?error')) {
this.authService.getSession();
}
}
signOut = async () => {
await this.authService.signOut();
};
async componentDidUpdate(prevProps) {
if (prevProps.shouldSignOut !== this.props.shouldSignOut) {
if (this.props.shouldSignOut) {
await this.signOut();
this.props.signOutSuccess();
}
}
}
//render nothing
render() {
return null;
}
}
const mapState = state => ({
username: state.auth.username,
signedIn: state.auth.signedIn,
shouldSignOut: state.auth.shouldSignOut
});
const mapDispatch = dispatch => ({
signIn: (username, profile) => dispatch(signIn(username, profile)),
signOutSuccess: () => dispatch(signOutSuccess())
});
export default connect(mapState, mapDispatch)(AuthService);
This AuthService.js is rendered upon loading the application. However When loading in IE11, there is an error var jsonDataObject = JSON.parse(jsonData); invalid character.
I have no idea why this is happening. I have investigated and came to the conclusion that this is going on within the package amazon-cognito-auth-js. I'm under the impression this package was made by amazon so I believe the package is not at fault, but I cannot see anyone else with this issue. Does anyone have any suggestions?
EDIT: I do have a polyfill
I saw you used arrow functions => in your code which is not supported by IE. You could use babel to compile it and any other ES6 syntax to ES5. For example, compile:
const cognitoSetup = props => {
...
}
to:
var cognitoSetup = function cognitoSetup(props) {
...
}
Besides, have you imported react-app-polyfill at the first line in your src/index.js? This is required for react app to run in IE 11. You could refer to the answer in this thread for detailed steps.
So, essentially, I'm using Create-React-App and I want to allow users to add data to redux either offline or online. I also want to sync redux with Firestore.
In my main attempt, I initialize my firebase settings:
// ./firebase/firebase.js
var firestoreDatabase;
firebase.initializeApp(config.firebase.config);
firebase.firestore().enablePersistence().then(() => {
firestoreDatabase = firebase.firestore();
});
export { firebase, firestoreDatabase };
Then, to make sure this has fired properly (this is definitely wrong, but I can't figure out the best place to catch the enablePersistence() return... ):
// src/index.js
import { firebase, firestoreDatabase } from "./firebase/firebase";
firebase.auth().onAuthStateChanged(user => {
store.dispatch(setReduxData()).then(() => {
if (firestoreDatabase) {
ReactDOM.render(application, document.getElementById("root"));
}
});
});
ACTIONS FILE
import { firestoreDatabase } from "../firebase/firebase";
export const setReduxData = () => {
return (dispatch, getState) => {
const uid = getState().auth.uid;
const data = { newData: '123' };
return firestoreDatabase
.collection("Users")
.doc(uid)
.collection("data")
.add(data)
.then(ref => {
// so, this never gets fired
dispatch(
addData({
id: ref.id,
...data
})
);
})
So the dispatch never gets fired, however, when I refresh the application, the data I entered { newData: '123' } is added to the store.
I think my entire way of handling this is wrong. I don't like exporting firestoreDatabase as undefined and then updating it when enablePersistence() returns...
I would like to just enablePersistence() once and then use the cache or the server depending on if the user is online or not... Redux should operate the same regardless...
Any thoughts and feedback are welcome!
So, I figured out how to load Firestore properly in my application:
In my firebase.js file:
import * as firebase from "firebase";
import config from "../config";
// https://firebase.google.com/docs/reference/js/
firebase.initializeApp(config.firebase.config);
const database = firebase.database();
const auth = firebase.auth();
const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
export { firebase, googleAuthProvider, auth, database };
Then, I added a firestore.js file:
import { firebase } from "./firebase";
import "firebase/firestore";
import { notification } from "antd";
firebase.firestore().settings({ timestampsInSnapshots: true });
const handleError = error => {
if (error === "failed-precondition") {
notification.open({
message: "Error",
description:
"Multiple tabs open, offline data only works in one tab at a a time."
});
} else if (error === "unimplemented") {
notification.open({
message: "Error",
description: "Cannot save offline on this browser."
});
}
};
export default firebase
.firestore()
.enablePersistence()
.then(() => firebase.firestore())
.catch(err => {
handleError(err.code);
return firebase.firestore();
});
And then I call firestore in my actions file:
import firestore from "../firebase/firestore";
return firestore
.then(db => {
var newData = db
.collection("Users")
.doc(uid)
.collection("userData")
.doc();
newData.set(data);
var id = newData.id;
dispatch(addData({ id, ...data }));
})
.catch(err => {
// notification
});
Essentially, I separated out my redux and Firestore, but ultimately they are connected through the Firestore id.