Problems with RealmDB objects in React Native with Reactotron - javascript

I'm having trouble with RealmDB objects in a React Native project, every query I do the RealmDB returns array of empty objects {} in reactotron and if I try to use rest/spread operator. However, when I access
attribute by attribute works. Someone had the same issue and managed to solve?
P.S: I already linked realm and reactotron in the project
Images about what I described
Reactotron: https://i.stack.imgur.com/OhN1D.png
Code: https://i.stack.imgur.com/gsNwk.png
An example of a piece of code where I try to discover the problem:
async getAllMov(){
try{
const realm = await getRealm();
const listaMov = realm.objects(MovSchema.schema.name);
console.tron.log(listaMov[4]);
const d = {...listaMov[4]};
console.tron.log(d);
let dados = {
movID: listaMov[4].movID,
titulo: listaMov[4].titulo,
descricao: listaMov[4].descricao,
valor: listaMov[4].valor,
tipo: listaMov[4].tipo
};
console.tron.log(dados);
}catch(e){
console.tron.log(e.message);
}
}

This solved my problem, I hope that helps you also:
export default function getRealmObjects = async (schemaName) => {
const realm = await getRealm();
var objects = realm.objects(schemaName);
//this is because realm put some obstacles when you try to modify it's objects, the solution found was to clone the results before return
let result = [];
for (let i = 0; i < objects.length; i++) {
let item = {};
for (const key in objects[i]) {
item[key] = objects[i][key];
}
result.push(item)
}
return result?.length > 0 ? result : [];
}
Basically you cannot modify realm objects, so you have to clone it before use.

Related

How to populate without using mongoose

I'm trying to implement populate() function without using mongoose in the code below:
`
course.students.forEach(async (student, i) => {
const s = await Student.findById(student._id);
console.log(s.toObject()); // gets student data properly
course.students[i] = s; // does not work
});
console.log(course.json());
`
I just want to update the students array with the data fetched. Can anyone explain me with the assignation doesn't works?
Thank you all! :)
forEach is not meant to be used with await, try to change to a for loop and use lean() to return a plain object from the query:
for (let i = 0; i < course.students.length; i++) {
const student = course.students[i];
course.students[i] = await Student.findById(student._id).lean();
}
console.log(course);

Proxy Object duplicate values

There is this code:
const priceWrap = ref(null)
const priceWrapSizes = useElementSize(priceWrap)
const priceWrapHeight = priceWrapSizes.height
const priceElementsQuantity = ref(3)
const priceTestWrapData:any = ref({})
function compositionPriceWrapElements (priceElementsNumber:any) {
const key = 'anyValue' + priceElementsNumber.toString()
Object.assign(priceTestWrapData, { [priceElementsNumber]: key })
priceTestWrapData.value[key] = 'test' + priceElementsNumber.toString()
console.log(priceElementsNumber)
console.log(priceTestWrapData.value)
}
watch(priceWrapHeight, (currentValue) => {
for (let priceElementsNumber = 0; priceElementsNumber < priceElementsQuantity.value; priceElementsNumber++) {
compositionPriceWrapElements(priceElementsNumber)
}
store.commit('gettingPriceWrapHeight', currentValue)
})
When it is worked out in DevTools, everything is displayed correctly
but there are problems with the console:
And the question is about it:
Why is each iterable key-value displayed on it three times in each log?
(And at this time the iterator in the console fulfills the 1st time as it should be.)
Doesn't it have something to do with proxy objects and Vue3 behavior in this context with them?
Is this generally normal behavior?

Javascript Object Issue not able to send particular key

Hi i have a weird javascript issue.Here's my code I am not able to send these keys in my designOrder object. My Object does not have these fronImage and backImage keys that i am sending in my code.
let designOrder = await dbCall();
let allImages = []
allImageIds.push(designOrders.frontImageId);
allImageIds.push(designOrders.backImageId);
allImages = await dbCall();
let allImagesHash = {};
allImages.forEach(obj) => {
obj.image = JSON.parse(image)
allImagesHash[image.id] = image;
}
if(designOrder.backImageId){
designOrder.backImage = allImagesHash[designOrder.backImageId]
}
// if i do console.log("1", designOrder.backImage) it will log the designOrder.backImage
if(designOrder.frontImageId){
designOrder.frontImage = allImagesHash[designOrder.frontImageId]
}
// if i do console.log("2", designOrder.frontImage) it will log the designOrder.backImage
// but while console.log("3", designOrder) it will not show the backImage and frontImage keys
return designOrder;
It actually solved it after the first dbCall() i have added this line of code and it worked.
designOrder = designOrder.toJSON();
toJson function is defined within the mongoose schema.

Javascript object retaining "old" properties, can't override?

I have the following code:
const readDataFromSql = () => {
// going to have to iterate through all known activities + load them here
let sql = "[...]"
return new Promise((resolve, reject) => {
executeSqlQuery(sql).then((dict) => {
let loadedData = [];
for (let key in dict) {
let newItemVal = new ItemVal("reading hw", 7121, progress.DONE);
loadedData.push(newItemVal);
}
resolve(loadedData);
});
});
}
ItemVal implementation:
class ItemVal {
constructor(name, time, type) {
this.name = name
this.time = time
this.type = type
}
}
Let's assume that newItemVal = "reading hwj", 5081, progress.PAUSED when readDataFromSql() first runs.
readDataFromSql() is then again called after some state changes -- where it repulls some information from a database and generates new values. What is perplexing, however, is that when it is called the second time, newItemVal still retains its old properties (attaching screenshot below).
Am I misusing the new keyword?
From what I can see in your example code, you are not mutating existing properties but creating a new object with the ItemVal constructor function and adding them to an array, that you then return as a resolved promise. Are you sure the examples you give a correct representation of what you are actually doing
Given that, I'm not sure what could be causing the issue you are having, but I would at least recommend a different structure for your code, using a simpler function for the itemVal.
Perhaps with this setup, you might get an error returned that might help you debug your issue.
const itemVal = (name, time, type) => ({ name, time, type })
const readDataFromSql = async () => {
try {
const sql = "[...]"
const dict = await executeSqlQuery(sql)
const loadedData = dict.map((key) =>
ItemVal("reading hw", 7121, progress.DONE)
)
return loadedData
} catch (error) {
return error
}
};
If the issue is not in the function, then I would assume that the way you handle the data, returned from the readDataFromSql function, is where the issue lies. You need to then share more details about your implementation.
const readDataFromSql = async () => {
let sql = "[...]"
------> await executeSqlQuery(sql).then((dict) => {
Use the await keyword instead of creating a new promise.
I did some modification and found that below code is working correctly, and updating the new values on each call.
const readDataFromSql = () => {
return new Promise((resolve, reject) => {
let loadedData = [];
let randomVal = Math.random();
let newItemVal = new ItemVal(randomVal*10, randomVal*100, randomVal*1000);
loadedData.push(newItemVal);
resolve(loadedData);
});
}
Could you recheck if you are using below line in the code, as it will instantiate object with same properties again and again.
let newItemVal = new ItemVal("reading hw", 7121, progress.DONE);
You can modify your code as below to simplify the problem.
const readDataFromSql = async () => {
// going to have to iterate through all known activities + load them here
let sql = "[...]" // define sql properly
let result = await executeSqlQuery(sql);
let loadedData = [];
for (let row in result) {
let newItemVal = new ItemVal(row.name, row.time, row.type);
loadedData.push(newItemVal);
}
return loadedData;
}
class ItemVal {
constructor(name, time, type) {
this.name = name
this.time = time
this.type = type
}
}
What you are talking about is an issue related to Object mutation in Redux, however, you didn't add any redux code. Anyway, you might be making some mistake while recreating(not mutating) the array.
General solution is the use spread operator as:
loadedData = [ ...loadedData.slice(0) , ...newloadedData]
In Dropdown.js line 188 instead of console.log-ing your variable write debugger;
This will function as a breakpoint. It will halt your code and you can inspect the value by hovering your mouse over the code BEFORE the newItemVal is changed again.
I can see in your screenshot that the newItemVal is modified again after you log it.

how to clone the mongoose query object in javascript

I am facing the problem of clone of the mongoose query object .Javascript the copy the one object into another object by call-by-ref but in my project there is scenario i need to copy one object into another object by call-by-value.
var query=domain.User.find({
deleted: false,
role: role
})
var query1=query;
I have the scenario change in the query object is not reflected in query1. I google and try so many way to clone the object but it does't work.The query object is used in another function for pagination and query1 object is used for count query.
1.I used to Object.clone(query1) error Object.clone is not function
2.I used Object.assign(query1) but it does't works fine.
3.I used other so many ways can anybody help me to sort this problem
Alternative solution using merge method:
const query = domain.User.find({
deleted: false,
role: role
}).skip(10).limit(10)
const countQuery = query.model.find().merge(query).skip(0).limit(0)
const [users, count] = await Promise.all([query, countQuery.count()])
you are trying to clone a cursor, but it is not the right approach, you probably just need to create another
like this:
var buildQuery = function() {
return domain.User.find({
deleted: false,
role: role
});
};
var query = buildQuery();
var query1 = buildQuery();
This is work for me:
const qc = sourceQuery.toConstructor();
const clonedQuery = new qc();
This code work in pagination function where sourceQuery passed as parameter and i dont known what models used. Also it work with aggregations and complex queries.
public async paging(
query: mongoose.DocumentQuery<mongoose.Document[], mongoose.Document>,
params,
transformer: any = null
) {
let page = Number(params.page);
if (!page) page = 1;
let page_size = Number(params.count);
if (!page_size) page_size = 100;
const qc = query.toConstructor();
const cq = new qc();
return cq.countDocuments().exec()
.then(async (total) => {
const s = params.sort;
if (s) {
query.sort(s);
}
query.limit(page_size);
query.skip(page_size * (page - 1));
let results = await query.exec();
if (transformer) {
results = await Promise.all(results.map((i) => transformer(i)));
}
const r = new DtoCollection();
r.pages = Math.ceil(total / page_size);
r.total = total;
(r.results as any) = results;
return r;
});
}
Sergii Stotskyi's answer works just fine and is very elegant, except that count is deprecated.
countDocuments or estimatedDocumentCount should be used instead.
However, this causes the error the limit must be positive. We can walk around this by set limit to a large integer.
const query = domain.User.find({
deleted: false,
role: role
}).skip(10).limit(10)
const countQuery = query.model.find().merge(query).skip(0).limit(Number.MAX_SAFE_INTEGER)
const [users, count] = await Promise.all([query, countQuery.countDocuments()])
Since mongoose v6 you can use Query.prototype.clone
E.g. for your code snippet:
const query = domain.User.find({
deleted: false,
role: role
})
const query1 = query.clone();

Categories