I have the following array that has been generated by the DocuSign API:
const signers = [
exports {
email: 'email1#gmail.com',
name: 'Test Name One',
recipientId: 'signer_1',
routingOrder: '1'
},
exports {
email: 'email2#gmail.com',
name: 'Test Name Two',
recipientId: 'signer_2',
routingOrder: '2'
},
exports {
email: 'email3#gmail.com',
name: 'Test Name Three',
recipientId: 'signer_3',
routingOrder: '3'
}
]
I need to get the index of the object in this array where the recipientId === 'signer_2' (for example), and have tried the following:
const signerKey = signers.filter(signerObj => {
console.log(signerObj) // returns "exports { ...email, name, etc }"
console.log(Object.keys[signerObj]) // returns undefined
console.log(signerObj.exports.recipientId) // returns undefined
console.log(typeof signerObj) // returns object
return signerObj.recipientId === 'signer_2' // returns undefined
})
How do I deal with finding data within these exports since they're not actual objects?
For some reason when I used JSON.stringify() then JSON.parse I was able to process everything normally:
const stringified = JSON.stringify(signers)
const signersObject = JSON.parse(stringified)
#casenonsensitive recommended using the lo-dash framework, which I haven't looked into yet, but could be a better solution.
Related
I used mongoose to create a schema that contains an array field called "favoriteFoods". But when I retrieved an instance and tried to push another food to this array, it failed and says "TypeError: Cannot read property 'push' of undefined".
I looked up the type of this field, it showed "undefined" instead of "array". Why is it happening?
const personSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
age: Number,
favoriteFoods: [String] //set up the type as an array of string
});
const Person = mongoose.model("Person", personSchema);
new Person({ name: "Lily", age: 5, favoriteFoods: "Vanilla Cake" }).save().catch(e => {
console.log(e);
})
Person.find({ name: "Lily" }, (err, data) => {
if (err) console.log(err);
console.log(data); // it gives me the object
console.log(data.favoriteFoods); // undefined
console.log(typeof (data.favoriteFoods)); // undefined
})
It looks like you are saying favoriteFoods takes an array of strings, but you are passing it a string value NOT in an array. What's more, there is also no guarantee that your new Person is done being saved before you try to find it since the operation happens asynchronously
The problem has been solved!
I made 2 changes -
Passing an array to favoriteFoods instead of a single value (Thank you #pytth!!)
Changing Model.find() to Model.findOne() because the 1st returned an array but the 2nd one returned an object
So the final code is:
const findLily = async () => {
const lily = new Person({ name: "Lily", age: 5, favoriteFoods: ["Vanilla Cake", "Lollipop"] });
await lily.save();
const found = await Person.find({ name: "Lily" });
found.favoriteFoods.push("hamburger");
await found.save();
}
Please correct me if I made any mistakes. Thanks! :)
I have a method
{payload.find((item) => item.dataKey === 'value')?.value || '-'}
and that's my payload that I pass normally as an array to the component with the method above, but it always returns the '-' sign:
export const mockedResponse = {
area: 'test',
bestValue: null,
comments: 'test comments',
controllerOnOffStatus: 'test',
currentValue: 1,
description: 'test description',
id: 'test id',
kind: 'test',
payload: [payload],
};
const payload = {
avg: 11,
timestamp: '22:00',
value: 11.07,
};
Any ideas why it cannot find the value? How should the mockedResponse look like, so the method would work?
You can not use a find() method for the objects. As your payload is an object like
const payload = {
avg: 11,
timestamp: '22:00',
value: 11.07,
};
And you want to check if the value key exists in the payload object, and if so return that value, otherwise return '-', you can use the following
payload.value || '-'
After your editing, I can see that you have converted the payload to the array.
You didn't have the dataKey property in the payload. If you want to check if the value exists in the item please try the following
{payload.find((item) => item.value)?.value || '-'}
Already my local Storage has some data 'Users' and in that object, I want to access an object inside it but I assigned it to another variable it gives me undefined
The error is
TypeError: Cannot read property 'length' of undefined:
27:console.log(initialState.length);
const TaskListContextProvider = props => {
const users = JSON.parse(localStorage.getItem('Users'))
var y;
var em;
for(var x=0;x<users.length;x++){
var obj = users[x];
if(obj.current == true){
y=x;
em = obj.Email;
break;
}else{
console.log('error');
}
}
console.log(users[y].Tasks.length);
if(users[y].Tasks.length == 0){
var initialState = []
}else{
console.log(users[y]);
console.log(users[y].Tasks);
var initialState = users[y].tasks
console.log(initialState.length);
}
my react code
my localStorage data:
[{Email: "rohit#devrushi.com", Password: "12345", current: true,…}]
0: {Email: "rohit#devrushi.com", Password: "12345", current: true,…}
Email: "rohit#devrushi.com"
Password: "12345"
current: true
Tasks: [{title: "qsw", desc: "wddc qwed", completed: false, id: "af5825b9-846a-466d-9ebe-1f09b100214d"}]
0: {title: "qsw", desc: "wddc qwed", completed: false, id: "af5825b9-846a-466d-9ebe-1f09b100214d"}
title: "qsw"
desc: "wddc qwed"
completed: false
id: "af5825b9-846a-466d-9ebe-1f09b100214d"
console.log(users[y].Tasks);
var initialState = users[y].tasks
Look at these two lines again. Do you spot the error?
...
It's Tasks vs tasks. Your Tasks property is an array, but your tasks property doesn't exist and hence is undefined.
You need to consistently write Tasks with upper-case T (or lower-case, but then everywhere lower-case!), because JavaScript is a case-sensitive language.
Let's say something returns a complex object:
const value = {
...,
client: { ... },
...
};
I want to test a bunch of properties, and for client I want to make sure that it has a certain name, but does not have id at all.
How do I implement it?
expect(value).toMatchObject({
...,
client: ???,
...
});
If it was just name I would have done client: { name: 'expected' }.
I tried client: { id: undefined, name: "expected" }, but undefined is not the same as "does not have a property".
I know I can do a separate case of expect(value).not.toHaveProperty('client.name'), but it would be great to just have one toMatchObject (I need this in multiple tests).
Sorted with this, but still keen to know if there is a better way:
expect.extend({
matchingAll(actual, expected) {
return { pass: expected.every(e => e.asymmetricMatch(actual)) };
}
});
expect(value).toMatchObject({
...,
client: expect.matchingAll([
expect.objectContaining({ name: 'expected' }),
expect.not.objectContaining({ id: expect.anything() }),
]),
...
});
clear the property undefined and after to compare
function clear(a){
Object.keys(a).forEach(key => {
if (a[key] === undefined) {
delete a[key];
}
});
}
let client = { id: undefined, name: "expected" }
clear(client )
console.log(client)
I have an array context.buildingFields.finished that looks like this:
[{ name: 'a' type: 'text', value: '1' }, { name: 'b' type: 'file', value: '2' }]
And I have a function that loops through that array to create a new one context.createPanoramasPayload with only the fields of type file:
function handleCreatePanoramas (uploadedPhoto, context, callback) {
const panoramasFields = context.buildingFields.finished
context.createPanoramasPayload = panoramasFields.map(field => {
if (field.type !== 'file') return
return {
name: 'index',
value: uploadedPhoto
}
})
callback(context.createPanoramasPayload)
}
}
I thought I would produce something like this (say with only one field of type file):
[{ name: 'b' type: 'file', value: '2' }]
However, what I'm getting is something like this:
[undefined, { name: 'b' type: 'file', value: '2' }]
Why is this? And how to modify the code to achieve what I want?
map returns an array that has the same length as the given array. It does not help to return just like that, as that will generate an undefined value in your mapped array. Instead you need to apply filter first:
context.createPanoramasPayload = panoramasFields.filter(field => {
return field.type === 'file';
}).map(field => {
return {
name: 'index',
value: uploadedPhoto
}
})
This keeps with a functional way of programming.
As a side note, since the callback functions now don't do anything else than return something, you can use the expression syntax for the arrow functions:
context.createPanoramasPayload = panoramasFields
.filter(field => field.type === 'file')
.map(field => ({
name: 'index',
value: uploadedPhoto
}));
You are using map function here, that means it will not reduce the length of the array. It return same length array. So use filter to get result.
This answer is an extension to #trincot's answer.
Using .filter + .map is not wrong, but it adds to extra iterations. Both these functions have their own specific use-case but when you need to do both, .reduce is more suited as you can manually parse object and return custom array/object.
Sample
context.createPanoramasPayload = panoramasFields.reduce(function(p, c) {
if (c.type === 'file')
p.push({
name: 'index',
value: uploadedPhoto
});
return p;
}, [])
Also note the use of anonymous function instead of arrow function(=>).
What arrow function does is it binds current context to the passed callback function, so that we can use this inside the callback. If you are using arrow function but not using this inside callback, you are wasting the efforts engine puts in binding context to the callback. For this reason, if you do not use this, in my understanding, its better to use anonymous function instead of arrow function.
Though its not wrong, but in my POV, it is a bad practice.