data not fetching from firestore in react native - react-native

i created a collection in firestore called user and added a document and gave it 7 fields, but when i try fetching the data back using onSnapshot it does not return back any data. this is the collection
this is my code:
firestore()
.collection('user')
.doc('LCqSZXM17WUWiWFahyj6')
.onSnapshot((row) => {
console.log(row.data());
});
in the console it logs an empty array
thanks in advance!!!

You need to include more information.
Anyway, do you check your access rule of the Firestore database?
const doc = db.collection('cities').doc('SF');
const observer = doc.onSnapshot(docSnapshot => {
console.log(`Received doc snapshot: ${docSnapshot}`);
// ...
}, err => {
console.log(`Encountered error: ${err}`);
});
The above code is official docs code. Check error callback first.

Related

React Native cheerio.load() not working properly neither is JSDOM library

Well I'm new to this app development thing especially react-native and I wanted to know when I'm trying to scrap a website using cheerio and axios in react-native and then save it to firebase realtime database in the following way:
and yes i have done all the imports and also initalized my app using firebaseConfig
const db = firebase.database();
async function loadFurniture() {
const Url = 'https://hoid.pk/product-category/bedroom/beds-bedroom/';
const html = await axios.get(Url); // fetch page
const $ = cheerio.load(html); //parse html String
const furniture = [];
$('.product-wrapper ').each((i, element) => {
const title = $(element).find('h2.product-name').text();
const imageUrl = $(element).find('img.primary_image').attr('src');
const price = $(element).find('span.woocommerce-Price-amount amount').text();
console.log(title);
furniture.push({ title, imageUrl, price });
});
// Save the furniture to the Firebase Realtime Database
db
.ref('/furniture/bed')
.set({
title: furniture.title,
price: furniture.price,
object_image : furniture.imageUrl,
})
.then(() => console.log('Data set.'));
console.log(furniture);
// Return the extracted information
return furniture;
}
and then calling this function in a button
<Button
title="Fetch"
onPress = {() => loadFurniture() }
/>
The data was not being scraped so I tried to console.log() the data being fetched.
Whenever I click the button there is no error but just a log [ Function initialize ] with respect to console.log(title)
And before anyone says yup I've looked into the structure and 9it does returns me my desired classes after axios.get()
I just want to know that if there's some error in my code or if I'm going wrong somewhere.
I tried to scrap furniture titles, images and prices from certain website and then save it to database for any further use but it's just not working.
I've checked my network issues the html page being scraped and everything else one can think of. Now i just want to know either my code is accurate or if there's some mistake.
I tired to scrap the data of same website using python and it scraps it perfectly.
Edit:
I found out that the cheerio.load() function is not working there was no problem with the database... Is there some problem with cheerio.load() in it's latest version "1.0.0-rc.12" ?? If so what's the solution... I've tried number of libraries and each is giving a different kind of error so cheerio might be the only possible solution so if there's an alternative way of using cheerio.load() in react native do let me know.

useInfiniteScroll utility of Vueuse is fetching same items again

Here is a reproducable stackblitz -
https://stackblitz.com/edit/nuxt-starter-jlzzah?file=components/users.vue
What's wrong? -
My code fetches 15 items, and with the bottom scroll event it should fetch another 15 different items but it just fetches same items again.
I've followed this bottom video for this implementation, it's okay in the video but not okay in my stackblitz code:
https://www.youtube.com/watch?v=WRnoQdIU-uE&t=3s&ab_channel=JohnKomarnicki
The only difference with this video is that he's using axios while i use useFetch of nuxt 3.
It's not really a cache issue. useFetch is "freezing" the API URL, the changes you make to the string directly will not be reliably reflected. If you want to add parameters to your API URL, use the query option of useFetch. This option is reactive, so you can use refs and the query will update with the refs. Alternatively, you can use the provided refresh() method
const limit = ref(10)
const skip = ref(20)
const { data: users, refresh: refreshUsers } = await useFetch(
'https://dummyjson.com/users',
{
query:{
limit,
skip
}
}
);
//use the data object directly to access the result
console.log(users.value)
//if you want to update users with different params later, simply change the ref and the query will update
limit.value = 23
//use refresh to manually refresh the query
refreshUsers()
This results in a first API call http://127.0.0.1:8000/api/tasks?limit=10&skip=20 and then a second with the updated values http://127.0.0.1:8000/api/tasks?limit=23&skip=20
You can leave the cache alone, as it is just a workaround, and will not work reliably.
[Updated] The useFetch() documentation is now updated as described below.
The query option is not well documented yet, as discussed in this nuxt issue. I've created a pull request on nuxt/framework to have it reflected in the documentation. Please see a full explanation below:
Using the query option, you can add search parameters to your query. This option is extended from unjs/ohmyfetch and is using ufo to create the URL. Objects are automatically stringified.
const param1 = ref('value1')
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains',{
query: { param1, param2: 'value2' }
})
This results in https://api.nuxtjs.dev/mountains?param1=value1&param2=value2
Nuxt3's useFetch uses caching by default. Use initialCache: false option to disable it:
const getUsers = async (limit, skip) => {
const { data: users } = await useFetch(
`https://dummyjson.com/users?limit=${limit}&skip=${skip}`,
{
initialCache: false,
}
);
//returning fetched value
return users.value.users;
};
But you probably should use plain $fetch instead of useFetch in this scenario to avoid caching:
const getUsers = async (limit, skip) => {
const { users } = await $fetch(
`https://dummyjson.com/users?limit=${limit}&skip=${skip}`
);
//returning fetched value
return users;
};

A better way to handle async saving to backend server and cloud storage from React Native app

In my React Native 0.63.2 app, after user uploads images of artwork, the app will do 2 things:
1. save artwork record and image records on backend server
2. save the images into cloud storage
Those 2 things are related and have to be done successfully all together. Here is the code:
const clickSave = async () => {
console.log("save art work");
try {
//save artwork to backend server
let art_obj = {
_device_id,
name,
description,
tag: (tagSelected.map((it) => it.name)),
note:'',
};
let img_array=[], oneImg;
imgs.forEach(ele => {
oneImg = {
fileName:"f"+helper.genRandomstring(8)+"_"+ele.fileName,
path: ele.path,
width: ele.width,
height: ele.height,
size_kb:Math.ceil(ele.size/1024),
image_data: ele.image_data,
};
img_array.push(oneImg);
});
art_obj.img_array = [...img_array];
art_obj = JSON.stringify(art_obj);
//assemble images
let url = `${GLOBAL.BASE_URL}/api/artworks/new`;
await helper.getAPI(url, _result, "POST", art_obj); //<<==#1. send artwork and image record to backend server
//save image to cloud storage
var storageAccessInfo = await helper.getStorageAccessInfo(stateVal.storageAccessInfo);
if (storageAccessInfo && storageAccessInfo !== "upToDate")
//update the context value
stateVal.updateStorageAccessInfo(storageAccessInfo);
//
let bucket_name = "oss-hz-1"; //<<<
const configuration = {
maxRetryCount: 3,
timeoutIntervalForRequest: 30,
timeoutIntervalForResource: 24 * 60 * 60
};
const STSConfig = {
AccessKeyId:accessInfo.accessKeyId,
SecretKeyId:accessInfo.accessKeySecret,
SecurityToken:accessInfo.securityToken
}
const endPoint = 'oss-cn-hangzhou.aliyuncs.com'; //<<<
const last_5_cell_number = _myself.cell.substring(myself.cell.length - 5);
let filePath, objkey;
img_array.forEach(item => {
console.log("init sts");
AliyunOSS.initWithSecurityToken(STSConfig.SecurityToken,STSConfig.AccessKeyId,STSConfig.SecretKeyId,endPoint,configuration)
//console.log("before upload", AliyunOSS);
objkey = `${last_5_cell_number}/${item.fileName}`; //virtual subdir and file name
filePath = item.path;
AliyunOSS.asyncUpload(bucket_name, objkey, filePath).then( (res) => { //<<==#2 send images to cloud storage with callback. But no action required after success.
console.log("Success : ", res) //<<==not really necessary to have console output
}).catch((error)=>{
console.log(error)
})
})
} catch(err) {
console.log(err);
return false;
};
};
The concern with the code above is that those 2 async calls may take long time to finish while user may be waiting for too long. After clicking saving button, user may just want to move to next page on user interface and leaves those everything behind. Is there a way to do so? is removing await (#1) and callback (#2) able to do that?
if you want to do both tasks in the background, then you can't use await. I see that you are using await on sending the images to the backend, so remove that and use .then().catch(); you don't need to remove the callback on #2.
If you need to make sure #1 finishes before doing #2, then you will need to move the code for #2 intp #1's promise resolving code (inside the .then()).
Now, for catching error. You will need some sort of error handling that alerts the user that an error had occurred and the user should trigger another upload. One thing you can do is a red banner. I'm sure there are packages out there that can do that for you.

How to solve duplicate page in ion-infinite-scroll ionic 4

I am using ionic 4 and I am doing pagination using ion-infinite-scroll. My problem is I always get the duplicate page problem. Can I know how to solve this duplicate problem? Here is my code in home.page.ts:
doInfinite(event) {
this.userService.getData().then(res => {
event.target.complete();
});
}
loadData(event) {
console.log('Load more data');
this.userService.getData().then(res => {
event.target.complete();
});
}
Here is home.html
<ion-infinite-scroll (ionInfinite)="loadData($event)">
<ion-infinite-scroll-content
loadingSpinner="bubbles"
loadingText="loading ...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
It depends what your userService.getData() looks like.
It doesn't look like you are telling it to start at an offset.
Each time you pull data down, you should assign that list data to some local on-page variable, let's say dataList.
Then use this.dataList.length as the starting index for your next data request.
So some pseudo-code for how this might work would be:
let dataFeed = [];
let startAtRecord = 0;
constructor() {
this.userService.getData(startAtRecord).then(res => {
this.dataFeed = res;
this.startAtRecord = this.dataService.length;
});
}
loadData(event) {
// ask for a batch of records, starting at `startAtRecord`
this.userService.getData(startAtRecord).then(res => {
// add the new res data to the existing dataFeed
this.dataFeed = [...this.dataFeed, ...res];
// keep track of the number of records loaded
this.startAtRecord = this.dataService.length;
event.target.complete();
});
}
Do you see what I'm saying? The data service has to load the next page of data so you don't get the same one back, so it needs to track where its starting the list from.

How to handle deep linking in react native / expo

I have posted about this previously but still struggling to get a working version.
I want to create a sharable link from my app to a screen within my app and be able to pass through an ID of sorts.
I have a link on my home screen opening a link to my expo app with 2 parameters passed through as a query string
const linkingUrl = 'exp://192.168.0.21:19000';
...
_handleNewGroup = async () => {
try {
const group_id = await this.createGroupId()
Linking.openURL(`${linkingUrl}?screen=camera&group_id=${group_id}`);
}catch(err){
console.log(`Unable to create group ${err}`)
}
};
Also in my home screen I have a handler that gets the current URL and extracts the query string from it and navigates to the camera screen with a group_id set
async handleLinkToCameraGroup(){
Linking.getInitialURL().then((url) => {
let queryString = url.replace(linkingUrl, '');
if (queryString) {
const data = qs.parse(queryString);
if(data.group_id) {
this.props.navigation.navigate('Camera', {group_id: data.group_id});
}
}
}).catch(err => console.error('An error occurred', err));
}
Several issues with this:
Once linked to the app with the query string set, the values don't get reset so they are always set and therefore handleLinkToCameraGroup keeps running and redirecting.
Because the URL is not an http formatted URL, it is hard to extract the query string. Parsing the query string returns this:
{
"?screen": "camera",
"group_id": "test",
}
It doesn't seem right having this logic in the home screen. Surely this should go in the app.js file. But this causes complications not being able to use Linking because the RootStackNavigator is a child of app.js so I do not believe I can navigate from this file?
Any help clarifying the best approach to deep linking would be greatly appreciated.