React native cannot set multiple arrayitems from Firebase in loop - firebase

I am trying to get data from Firebase realtime database in the loop and set array items,
but just the last item can set.
it's looking like synchronize problems I tried a lot of things but couldn't solve it.
import FireBaseConnection from '../classes/firebaseconnection.js';
const getComments = () => {
let cardatafetch=[]
FireBaseConnection.GetData('/PostComments/1234').then((comments) => {
for (i in comments) {
cardatafetch.push(comment[i])
}
for (j in cardatafetch) {
var UserId = cardatafetch[j]["UserID"]
FireBaseConnection.GetData('/Users/'+UserId).then((user) => {
cardatafetch[j].ProfilePicture=user["ProfilePicture"]
})
.catch((error) => {
console.log(error)
});
}
console.log(cardatafetch)
}).catch((error) => {
console.log(error)
});
}
}
Console Output is
Same problem also during get images from storage
for (j in cardatafetch) {
FireBaseConnection.GetImage().then((obj) => {
cardatafetch[j].ProfilePicture=obj
})
.catch((error) => {
console.log(error)
});
}
FireBaseConnection Class
import database from '#react-native-firebase/database';
import storage from '#react-native-firebase/storage';
import { utils } from '#react-native-firebase/app';
class FireBaseConnection
{
static async GetData(refValue) {
let data;
await database()
.ref(refValue)
.once('value')
.then(snapshot => {
data = snapshot.val();
});
return data;
}
static async GetImage(imgValue) {
const reference = storage().ref(imgValue);
let imagePath= await reference.getDownloadURL().then(result =>result);
return imagePath;
}
}
export default FireBaseConnection;

Try below code, what I have done is put your code inside last iteration of the loop so it will be implemented only once when all the items are pushed in the array.
import FireBaseConnection from '../classes/firebaseconnection.js';
const getComments = () => {
return new Promise((resolve, reject) => {
let commentsArr = [];
FireBaseConnection.GetData('/PostComments/1234').then((comments) => {
Object.keys(comments).forEach((key, index) => {
commentsArr.push(comments[key])
if(index == Object.keys(comments).length-1) {
resolve(commentsArr);
}
});
}).catch((error) => {
console.log(error)
});
});
}
const addImagesToComment = () => {
this.getComments().then((comments) => {
var finalArr = [];
comments.forEach((comment, index) => {
var tempComment = comment;
var UserId = comment["UserID"]
FireBaseConnection.GetData('/Users/' + UserId).then((user) => {
tempComment.ProfilePicture = user["ProfilePicture"]
finalArr.push(tempComment);
}).catch((error) => {
console.log(error)
});
if(index == comments.length-1) {
console.log(finalArr)
}
});
});
}
Try calling getComments function.

Related

Solution to prefetch in a component on nextjs

I'm looking for a solution/module where I don't need to inject inital/fallback data for swr/react-query things from getServerSideProps. Like...
from
// fetcher.ts
export default fetcher = async (url: string) => {
return await fetch(url)
.then(res => res.json())
}
// getUserData.ts
export default function getUserData() {
return fetcher('/api')
}
// index.tsx
const Page = (props: {
// I know this typing doesn't work, only to deliver my intention
userData: Awaited<ReturnType<typeof getServerSideProps>>['props']
}) => {
const { data } = useSWR('/api', fetcher, {
fallbackData: props.userData,
})
// ...SSR with data...
}
export const getServerSideProps = async (ctx: ...) => {
const userData = await getUserData()
return {
props: {
userData,
},
}
}
to
// useUserData.ts
const fetcher = async (url: string) => {
return await fetch(url)
.then(res => res.json())
};
const url = '/api';
function useUserData() {
let fallbackData: Awaited<ReturnType<typeof fetcher>>;
if (typeof window === 'undefined') {
fallbackData = await fetcher(url);
}
const data = useSWR(
url,
fetcher,
{
fallbackData: fallbackData!,
}
);
return data;
}
// index.tsx
const Page = () => {
const data = useUserData()
// ...SSR with data...
}
My goal is making things related to userData modularized into a component.

How to read array of objects with data from fireabse

I have a function that create tasks and writing it in firebase real time database.
export const createNewTask = (task) => new Promise(async (resolve, reject) => {
try {
await database().ref('tasks').child(auth().currentUser.uid).child(task.taskCreationDate.toString()).set(task);
resolve();
} catch (e) {
reject(e);
}
});
And it's working good :
Now, I have a socond functions that should read that tasks.
export const fetchTasks = () => (dispatch) => new Promise(async (resolve, reject) => {
try {
const snapshot = await database().ref('tasks').child(auth().currentUser.uid).once('value');
if (snapshot.exists) {
const tasks = snapshot.val();
dispatch({
type: FETCH_TASKS,
payload: tasks,
});
resolve(tasks);
} else {
resolve(snapshot);
}
} catch (e) {
reject(e);
}
});
And here is the problem:
When I'm using useSelector in my home screen const tasks = useSelector(state => state.GeneralReducer.taskList);
The tasks list is undefiend.
When I used mock data with same objects , it's work fine.
How can I get a list of task?
Ok , fixed it by adding :
Object.keys(data).map(key => ({...data[key], id: key}));
to the function fetchTasks.
export const fetchTasks = () => (dispatch) => new Promise(async (resolve, reject) => {
try {
const snapshot = await database().ref('tasks').child(auth().currentUser.uid).once('value');
if (snapshot.exists) {
const data = snapshot.val();
const tasks = Object.keys(data).map(key => ({...data[key], id: key}));
dispatch({
type: FETCH_TASKS,
payload: tasks,
});
resolve(tasks);
} else {
resolve(snapshot);
}
} catch (e) {
reject(e);
}
});

Microsoft Teams Tab with MSAL sign in

I've been working on getting a custom tab working in MS teams using MSAL. I've been following the example here: https://github.com/nmetulev/teams-msal and I can generate a token. I then try to forward this token to my API, where I build a security claim and call SignInAsync() to persist the cookie.
This then gets stored, and I forward to my standard page, but this does not page auth (I get unauthorized). Is there something I'm missing that I need to be doing?
Auth Page
const signIn = () => {
msalApp.acquireTokenRedirect(authenticationParameters);
}
const handleSignedIn = () => {
microsoftTeams.initialize();
microsoftTeams.authentication.notifySuccess();
}
const handleSignedOut = (error) => {
microsoftTeams.initialize();
microsoftTeams.authentication.notifyFailure(error);
}
const handleErrorReceived = (authError, accountState) => {
console.log(authError, accountState);
handleSignedOut({authError});
}
const handleTokenReceived = (response) => {
console.log(response);
handleSignedIn();
}
// MAIN
const msalApp = new Msal.UserAgentApplication(msalConfig);
msalApp.handleRedirectCallback((response) => handleTokenReceived(response), (error, state) => handleErrorReceived(error, state));
microsoftTeams.initialize();
microsoftTeams.getContext((context) => {
authenticationParameters = {
scopes: scopes,
loginHint: context.loginHint
};
setTimeout(() => {
attemptSilentSignIn().then(success => {
if (success) {
handleSignedIn();
} else {
signIn();
}
});
},
4000);
});
Sign In Page:
const attemptSilentSignIn = () => {
renderLoading();
if (msalApp.getAccount()) {
msalApp.acquireTokenSilent({ scopes }).then((response) => {
if (response && response.accessToken) {
handleSignedIn(response.accessToken);
} else {
handleSignedOut();
}
}, () => {
handleSignedOut();
})
} else {
handleSignedOut();
}
}
const signIn = () => {
renderLoading();
microsoftTeams.initialize(() => {
microsoftTeams.authentication.authenticate({
url: window.location.origin + "/resources/TeamsAuthFlow.html",
successCallback: () => attemptSilentSignIn(),
failureCallback: (error) => renderError(error)
});
});
}
const handleSignedIn = (accessToken) => {
microsoftTeams.initialize();
microsoftTeams.getContext((context) => {
var tenant = $("<input>").attr("id", "TenantId").attr("name", "TenantId").val(context.tid);
var token = $("<input>").attr("id", "AuthToken").attr("name", "AuthToken").val(accessToken);
var form = $("<form>").css("display", "none").attr("id", "target").attr("method", "POST").attr("action", "/api/TeamsTabSignIn").append(tenant).append(token).submit();
$("body").append(form);
$("#target").submit();
});
}
const handleSignedOut = () => {
renderSignedOutView();
}
// MAIN
let app = document.querySelector('.app');
const msalApp = new Msal.UserAgentApplication(msalConfig);
attemptSilentSignIn();
let authenticationParameters = null;
const handleErrorReceived = (authError, accountState) => {
console.log(authError, accountState);
handleSignedOut({ authError });
}
const handleTokenReceived = (response) => {
console.log(response);
handleSignedIn();
}
API Call
TenantId = Context.Request.Form["TenantId"];
AuthToken = Context.Request.Form["AuthToken"];
var principal = await _authHelper.SetPlatformUser(TenantId, AuthToken);
if (principal is ClaimsPrincipal cp)
{
await Context.SignInAsync("Cookies", cp, new AuthenticationProperties { IsPersistent = true });
Response.Redirect("/app/teamspage/Ticket");
}

How to use chained promises inside firebase functions?

I created a firebase function that updates the like count of an comment or post when a new like document is created.
But it throws an 404 error.
exports.updateLikeCount = functions.firestore
.document('likes')
.onCreate((snap, context) => {
const likeObj = snap.data();
if(likeObj.isComment) {
const { _comment } = likeObj;
const commentRef = fstore.collection('comments').doc(_comment);
return commentRef.get()
.then(doc => {
let { likes } = doc.data();
++likes;
return commentRef.update({
likes
});
});
}else {
const { _post } = likeObj;
const postRef = fstore.collection('posts').doc(_post);
return postRef.get()
.then(doc => {
let { likes } = doc.data();
++likes;
return postRef.update({
likes
});
});
}
});
NOTE:
_post and _comment are post ID and comment ID respectively

How can I use Ionic 2 Pulling Refresher in my app?

Hi all I'M working on angularjs 2/ionic2 mobile app , i need to do pulling refresher in my app, we have tried this link:- https://ionicframework.com/docs/v2/api/components/refresher/Refresher/ process i got refreshing the page but it's not get dismissLoader, we have given the images of my app refreshing:-
we don't know where we did the mistake and where we need to add the correct functionality in my project...
while we pulling the page it's refreshing but it's not get dismiss, Refreshing text and icon showing it's not get dismissed...
what we expecting once we pulled the page it's need to refresh after that refreshing text and icon need to be dismiss...
**we added coding only in html:-****
<ion-refresher (ionRefresh)="setFilteredItems($event)">
<ion-refresher-content refreshingSpinner="circles" refreshingText="Refreshing...">
</ion-refresher-content>
</ion-refresher>
we have not added anything in type script part...so please check and update the solution please....
we have created example Plunker
please update the plunker as well to know the solution, thanks.....
My Type Script constructor code:-
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { GlobalStateService } from '../../services/global-state.service';
import { AccountSigninPage } from '../account-signin/account-signin';
import { AccountSignupPage } from '../account-signup/account-signup';
import { ActivityAddPage } from '../activity-add/activity-add';
import { Activity } from "../../services/actopi-sdk/model/Activity";
import { UserLoginService } from "../../services/account-management.service";
import { ResourceListPage } from '../resource-list/resource-list';
import { IamAuthorizerClient } from "../../services/actopi-api.service";
import { CustomAuthorizerClient, NoAuthorizationClient, UserPoolsAuthorizerClient } from "../../services/actopi-api.service";
import { Config } from '../../config/config'
import { Logger } from '../../services/logger.service';
import 'rxjs/add/operator/debounceTime';
import { FormControl } from '#angular/forms';
declare const AWS: any;
#Component({
templateUrl: 'activity-list.html',
})
export class ActivityListPage {
initialized = false;
accountSigninPage = AccountSigninPage;
accountSignupPage = AccountSignupPage;
activityAddPage = ActivityAddPage;
activitys: Activity[] = [];
resourceListPage = ResourceListPage;
searchTerm: string = '';
searchControl: FormControl;
displayDeleteActivityConfirmation(activityId, activityName) {
console.log("Deleting activityID " + activityId);
let confirm = this.globals.getAlertController().create({
title: 'Delete activity?',
message: `Are you sure you want to delete [<b>${activityName}</b>]? All resources and bookings associated with [<b>${activityName}</b>] will also be deleted!`,
buttons: [
{
text: 'Cancel',
handler: () => { /* do nothing */ }
},
{
text: 'OK',
handler: () => {
this.deleteActivity(activityId)
.then(() => {
this.globals.dismissLoader();
this.globals.displayToast(`Activity [${activityName}] has been successfully deleted`);
})
.catch((err) => {
this.globals.dismissLoader();
this.globals.displayAlert('Error encountered',
'Delete failed. Please check the console logs for more information.');
console.log(err);
});
}
}
]
});
confirm.present();
}
deleteActivity(activityId): Promise<void> {
return new Promise<void>((resolve, reject) => {
// delete from the database
this.globals.displayLoader("Deleting...");
this.customAuthClient.getClient().activitysDelete(activityId).subscribe(
() => {
// remove the item from the activitys array
let index = this.activitys.findIndex(activity => { return activity.activityId == activityId });
if (index > -1) {
this.activitys.splice(index, 1);
}
resolve();
},
(err) => {
reject(err);
}
);
});
}
gotoResourceListPage(activity) {
this.navCtrl.push(ResourceListPage, activity);
}
filterItems(searchTerm): void {
this.activitys = [];
this.userPoolsAuthClient.getClient().activitysList().subscribe(
(data) => {
this.activitys = data.items.filter((activity) => {
return activity.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
});
this.globals.dismissLoader();
this.initialized = true;
},
(err) => {
this.globals.dismissLoader();
this.initialized = true;
console.error(err);
this.globals.displayAlert('Error encountered',
`An error occurred when trying to load the activitys. Please check the console logs for more information.`)
});
}
loadActivitysWithAuth(): void {
this.activitys = [];
this.userPoolsAuthClient.getClient().activitysList().subscribe(
(data) => {
// this.activitys = data.items
// sort by name
let searchTerm: string = '';
// this.activitys = data.items.sort((a, b) => {
// return a.name.localeCompare(b.name);
// });
this.globals.dismissLoader();
this.initialized = true;
},
(err) => {
this.globals.dismissLoader();
this.initialized = true;
console.error(err);
this.globals.displayAlert('Error encountered',
`An error occurred when trying to load the activitys. Please check the console logs for more information.`)
}
);
};
loadActivitysWithoutAuth(): void {
this.activitys = [];
this.noAuthClient.getClient().activitysList().subscribe(
(data) => {
// this.activitys = data.items
// sort by name
this.activitys = data.items.sort((a, b) => {
return a.name.localeCompare(b.name);
});
this.globals.dismissLoader();
this.initialized = true;
},
(err) => {
this.globals.dismissLoader();
this.initialized = true;
console.error(err);
this.globals.displayAlert('Error encountered',
`An error occurred when trying to load the activitys. Please check the console logs for more information.`)
}
);
};
constructor(private navCtrl: NavController, public globals: GlobalStateService, private noAuthClient: NoAuthorizationClient, private customAuthClient: CustomAuthorizerClient, private userPoolsAuthClient: UserPoolsAuthorizerClient, private authClient: IamAuthorizerClient) {
this.searchControl = new FormControl();
}
ionViewDidEnter() {
Logger.banner("Activitys");
this.activitys = [];
if (!this.initialized) {
this.initialized = false;
if (UserLoginService.getAwsAccessKey() != null) {
// if (CognitoUtil.getUserState() === UserState.SignedIn) {
// console.log(AWS.config.credentials);
UserLoginService.getAwsCredentials()
.then((data) => {
this.globals.displayLoader("Loading...");
this.setFilteredItems(refresher);
this.searchControl.valueChanges.debounceTime(700).subscribe(search => {
this.globals.displayLoader("Loading...");
this.setFilteredItems(refresher);
this.globals.dismissLoader();
});
})
.catch((err) => {
console.log("ERROR: Unable to load activitys!");
console.log(err)
})
}
}
}
setFilteredItems(refresher) {
return this.filterItems(this.searchTerm);
refresher.complete();
}
}
You need to call refresher.complete() to dismiss your refresher once loading of new data is done..
setFilteredItems(refresher?:any){
//async call to load.
// in the then function
if(refresher)
refresher.complete();
}
}
The refresher is sent from the html onRefresh. With ? you can call without passing object in your code.
this.setFilteredItems();
Also consider refactoring your code. You should ideally call complete after async task ia done and no point in returning another function to the html side and calling complete after return will just end up as dead code.

Resources