Uncaught TypeError: 'ownKeys' on proxy: trap result did not include 'length' - ecmascript-6

as header above, I have a code here, try to trap array and when I loop keys of proxy-array object, it gives me a error.
//random array
let userinfo = [1,2,3,4,5,6]
//trap own keys
userinfo = new Proxy(userinfo,{
ownKeys(target){
return Object.keys(target).filter(item=> item>2)
}
})
for(let key in userinfo){ //cause error
console.log(key)
}

Object.keys will not return everything ownKeys expects because it will omit symbol keys and importantly for things case it will include non-enumerable properties. You need to at a minimum do
ownKeys(target){
return Reflect.ownKeys(target).filter(key => {
const numKey = +key;
return Number.isNaN(numKey) || numKey > 2;
});
}
To spell that out, your code has two primary issues:
ownKeys and Object.keys return different things
Object.keys([1,2,3]) => [ '0', '1', '2' ]
Reflect.ownKeys([1,2,3]) => [ '0', '1', '2', 'length' ]
.filter(item=> item>2) assumes that all keys will be numeric, and 'length' > 2 returns false so your filter would have removed length from the array incorrectly. You should only remove numeric keys <= 2.

Related

How do I resolve a map value called on null

I have a contact model that uses maps but the return is null thus causing aysnc suspension. I have tried tried setting these maps to return an empty list but to no avail do I manage to resolve the issue.
ContactModel{
//factory method constructor
emails: List<Email>.from(parsedJson['Emails'].map((x)=>Email.fromJson(x))),
tasks: List<Tasks>.from(parsedJson["Tasks"].map((x) => Tasks.fromJson(x))),
notes: List<Notes>.from(parsedJson["Notes"].map((x) => Notes.fromJson(x))),
}
The error returns as : No such method map called on null. Receiver null
I have tried to resolve the issue by writing it as such
ContactModel{
//factory method constructor
emails: List<Email>.from(parsedJson['Emails'].map((x)=>Email.fromJson(x))).toList() ?? [],
tasks: List<Tasks>.from(parsedJson["Tasks"].map((x) => Tasks.fromJson(x))).toList() ?? [],
notes: List<Notes>.from(parsedJson["Notes"].map((x) => Notes.fromJson(x))).toList() ?? [],
}
You can try null checking the json like so :
ContactModel{
emails: parsedJson['Emails'] != null ? List<Email>.from(parsedJson['Emails'].map((x)=>Email.fromJson(x))).toList() : [],
tasks: parsedJson['Tasks'] != null ? List<Tasks>.from(parsedJson["Tasks"].map((x) => Tasks.fromJson(x))).toList() : [],
notes:parsedJson['Notes'] != null ? List<Notes>.from(parsedJson["Notes"].map((x) => Notes.fromJson(x))).toList() : [],
}
Basically, I always check 2 things when working with JSON types :
You must check your JSON contains the key you're looking for
You must check null value being returned if the key exist.
I recommend you doing this double check like this :
if(parsedJson.isNotEmpty) {
List<dynamic> emails = [];
if (parsedJson.containsKey('Email') && parsedJson['Email'] is List) {
emails = List<Email>.from(parsedJson['Emails'].map((x)=>Email.fromJson(x)))
}
ContactModel({emails: emails});
}
This way, you always make sure you've got the right type, and avoid production error (imagine your API going nuts). It's more verbose, I know, but to me, good code requires accuracy

Can't figure out a query to upsert collection into a tablr

I want to insert or update rows into my models table. But can't figure out the query.
SmStudentAttendance This is my model.
$students is my collection.
I have put the collection fields in arrays.
foreach ($students as $student) {
array_push($temp_id, $student->id);
array_push($temp_lastname, $student->last_name);
array_push($temp_academic_id, $student->academic_id);
array_push($temp_attendance, 'P');
array_push($temp_attendancedate, $date);
array_push($temp_schoolid, '1');
array_push($temp_updatedby, '1');
array_push($temp_createdby, '1');
}
Now I want to insert them if a row for the student_id and attendance_date is not present in the table else update if it already exists.
This is the query:
SmStudentAttendance::upsert('attendance_type', $temp_attendance, 'attendance_date', $temp_attendancedate, 'student_id', $temp_id, 'created_by', $temp_createdby, 'updated_by', $temp_updatedby, 'school_id', $temp_schoolid, 'academic_id', $temp_academic_id);
Error I am geting:
Argument 1 passed to Illuminate\Database\Eloquent\Builder::upsert() must be of the type array, string given, called in D:\xampp\htdocs\sms\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php on line 23
You're creating your arrays for columns rather than rows, this will cause problems, consider this code instead:
$studentRows = [];
foreach ($students as $student) {
$studentRows[] = [
'id' => $student->id,
'last_name' => $student->last_name,
'academic_id' => $student->academic_id,
'attendance_type' => 'P',
'attendance_date' => $date,
// .... rest of the fields
]
}
SmStudentAttendance::upsert($studentRows, [ 'id', 'last_name', 'academic_id' ], [ 'attendance_type', 'attendance_date' ]);
In general the idea is you pass it an array of rows you want to upsert, then an array of fields to match and an array of fields to update. Then Laravel will make queries find all rows that match the fields specified and update those and then insert the rows that did not match the given fields.
The error message, "Argument 1 passed to Illuminate\Database\Eloquent\Builder::upsert() must be of the type array, string given", suggests that the first parameter needs to be an array rather than the string you are setting.
Take a look at the documentation for this at https://laravel.com/docs/8.x/eloquent#upserts for an example. The method accepts two arrays. The first contains all of the data to be updated, the second the fields which uniquely identify the record. You will need to update your method call to match this syntax.

Remove duplicate object copies from array of objects

I have an array of objects that I get from an API. The property names are dynamic (meaning I don't have an extensive list of all of them). How can I get an array of all distinct objects? The contract specifies that if key is equal value is also equal. I tried to look around but I found nothing quite like this problem.
[ 20:31:28
{
'product-management': 'Product management'
},
{
'product-development': 'Product development'
},
{
'client-work': 'Client work'
},
{
'client-work': 'Client work'
},
{
'product-development': 'Product development'
},
{
'client-work': 'Client work'
},
{
'product-development': 'Product development'
}
]
Spread the array into Object.assign() to merge all objects to a single one. Since all objects properties are unique, this will leave only one key (and value) from the duplicates. Then convert to [key, value] pairs with Object.entries(), and map back to individual objects:
const data = [{"product-management":"Product management"},{"product-development":"Product development"},{"client-work":"Client work"},{"client-work":"Client work"},{"product-development":"Product development"},{"client-work":"Client work"},{"product-development":"Product development"}]
const result = Object.entries(Object.assign({}, ...data))
.map(([k, v]) => ({ [k]: v }))
console.log(result)
Going with #Bergi's suggestion, you can also convert this to a saner API while removing duplicates:
const data = [{"product-management":"Product management"},{"product-development":"Product development"},{"client-work":"Client work"},{"client-work":"Client work"},{"product-development":"Product development"},{"client-work":"Client work"},{"product-development":"Product development"}]
const result = Object.entries(Object.assign({}, ...data))
.map(([key, value]) => ({ key, value }))
console.log(result)

Sequelize raw queries TextRow and getting data out of it

Given this query here,
let output = [];
const sql = `select * from coredb.account LIMIT ${offset},${limit}`;
let data = await sequelize.query(sql, null, {raw: true, type: sequelize.QueryTypes.SELECT});
data.forEach((item) => {
console.log(item['id'], item.id); // <-- output says "undefined, undefined"
});
the data variable is indeed hydrated with the right row data when using console.log to inspect it.
But, when I try to access the individual properties, they only ever come back as undefined. This TextRow object that Sequelize seems to return the result in doesn't seem to want to let me access then explicit rows.
Just curious what i'm missing here, am I missing an option?
I agree, Sequalize raw queries are not intuitive. You don't need the null or raw: true flag. Something like this should work:
let data = await sequelize.query(sql, {type: sequelize.QueryTypes.SELECT});
When I tried this, "data" was an array of two objects, each being the query result. So, the properties can be accessed by using index [0].... e.g.
data[0].forEach((item) => {
console.log(item['id'], item.id); // <-- output says "undefined, undefined"
});
Not yet sure WHY this occurs!
EDIT - it's because .query() should have only two arguments. Changing the call to: sequelize.query(sql, {raw: true, type: sequelize.QueryTypes.SELECT}) resulted in data being a single array (as expected).
Finally I was able to find the solution for it.
You just need to make a new array and push data into it by finding bases on key name like this:
suppose we have data in students object:
let finalArray = new Array();
for (var k in students ) {
finalArray.push(students[k])
}
console.log(finalArray) // Normal JSON array object :)
m.sequelize.query(sql, {
model,
mapToModel: true
})
.then(model => res.status(200).send(model))
.catch(error => res.status(400).send(error.toString())
})

Unable to add new key-value pair dynamically to a STATE JSON Array in React App

I am trying to add a new key-value pair to the already loaded JSON Array. I am adding the new key-value pair to customize the header column cells in react bootstrap table but getting the below errors. Can any one please help?
'Columns' in the below state is where I wanted to add new key-value pair
state = {
data: MYResult.Products || [],
actualData: MYResult.Products || [],
columns: MYResult.ParametricList_Attributes || [],
isCompareClicked: false,
isDisabled: true,
selected: []
};
This is how I am adding the key-value pair -
componentDidMount(){
checkbox = (column, colIndex) => {
return (
<h5>{ column.text }<checkbox/></h5>
);
}
console.log(this.state.columns) ;
newColumn = this.state.columns.map((column) => {
return {...column, headerFormatter: checkbox};
});
this.setState({columns: newColumn });
}
Full code here - https://codesandbox.io/s/o1r988qkz Please uncomment the componentDidMount() to see the issue
Firstly, there's a typo in dcolumn and column.
And regarding the not defined error, you need to define it using const. Use like:
const checkbox = (column, colIndex) => {
return (
<h5>{column.text}<checkbox /></h5>
);
}
JavaScript variables need to be declared when they are used. Public class syntax can not be used everywhere. The error you're getting is self-evident - 'checkbox is not defined'.
Refer this on how to use it: https://tylermcginnis.com/javascript-private-and-public-class-fields/
I simply declared the undeclared variables in your example and the code worked.