I am attempting to use inquirer to collect user input, that is turned into an object, it is then passed into a class constructor. Everything seems to working the way I want it to accept the resulting array of objects after they are passed though the classes come out in a way that is confusing me,
when I console.log the array that contains the objects that are returned by my classes this is what comes out:
[
Manager {
name: 'bob',
id: '24',
email: 'bob.com',
officeNumber: '1'
},
Engineer {
name: 'jack',
id: '347',
email: 'jack.com',
github: 'jackolantern'
},
Intern {
name: 'sally',
id: '987',
email: 'sally.com',
school: 'UCF'
}
]
Here is an example of one of the classes:
class Manager extends Employee {
constructor (employeeObj) {
super (employeeObj);
this.name = employeeObj.name;
this.id = employeeObj.id;
this.email = employeeObj.email;
this.officeNumber = employeeObj.officeNumber;
}
getOfficeNumber () {
return this.officeNumber;
}
getRoll () {
return "Manager";
}
}
module.exports = Manager;
and this is how the objects are passed into the classes:
const prompts = async () => {
let employeeObj = {};
const employee = await inquirer.prompt(addEmployee);
switch(employee.addEmployee){
case 'Manager':
employeeObj = await managerQuestions();
const manager = new Manager(employeeObj);
output.push(manager);
if(employeeObj.addAnother){
return prompts();
} else {
complete();
}
break;
case 'Engineer':
employeeObj = await engineerQuestions();
const engineer = new Engineer(employeeObj)
output.push(engineer)
if(employeeObj.addAnother){
return prompts();
} else {
complete();
}
break;
case 'Intern':
employeeObj = await internQuestions();
const intern = new Intern(employeeObj)
output.push(intern)
if(employeeObj.addAnother){
return prompts();
} else {
complete();
}
break;
default:
console.log('you have reached the default switch statement. thant should not happen. Please try again!');
}
}
what I cant seem to figure out, is why the "roll" for each object (Manager, Engineer, Intern) is being placed outside the corresponding object and not inside it. I was able to add a this.roll = "manager" inside the constructor and as expected it added in a property called roll with a value of "manager" which will work just fine for what I need to do, but how do I get rid of that Manager, Engineer, and Intern that shows up before each object in the output array, or can it be moved inside the object?
thank you for taking the time to read through all this.
Related
I have one object named waA which is required in final step. But in ReactJS the new object is not getting updated in the previous object using switch in a function.
The object code is given below:
waA = {
jsonObject: {
wAConfigur: {}
}
}
var updatewaA = waA.jsonObject.wAConfigur;
The button has onClick event and its function is:
function next(){
switch(case){
case 1:
const bD = {
'name': 'john',
'title': 'Boy',
}
updatewaA.configureSet = bD;
break;
case 1:
const cE = {
'age': 34,
}
updatewaA.newDate = bD;
break;
}
}
The final Object which is needed is:
{
jsonObject: {
wAConfigur: {
configureSet: {
'name': 'john',
'title': 'Boy',
},
newDate: {
'age': 34
}
}
}
}
But for some reason in ReactJS the object is not getting updated.
How can I be able to do it? Thank you.
You need to store the object inside the react state to later make it update and render new state to the dom.
import {useState} from "react"
// new state waA and updater function setWaA
const [waA, setWaA] = useState({
jsonObject: {
wAConfigur: {},
},
})
function next(number){
switch(number){
case 1:
const bD = {
'name': 'john',
'title': 'Boy',
}
// here we added configureSet
setWaA(prevWaA => {
...prevWaA,
jsonObject: {
...prevWaA.jsonObject,
configureSet = bD
}
})
const cE = {
'age': 34,
}
// here we added newDate
setWaA(prevWaA => {
...prevWaA,
jsonObject: {
...prevWaA.jsonObject,
newDate = cE
}
})
break;
}
}
Continuing on the answer given by Abhishek, in ReactJS you should take care of using objects and arrays in a functional way, keeping them constants throughout the entire application scope so that you don't change your variables during usage.
This ensures that each step the variable is used in is "new" and unchanged, rather, cloned from the previous value without actually changing the previous one. It's also best because objects and arrays are references in memory and are not actual values, hence if you assign an object or array, you are actually assigning the reference, not the value of it.
With React you can spread the object or array to clone it but take care of the object because it's not a deep clone like Lodash would do, so you have to do as specified by Abhiskek.
import { useState } from 'react'
function Task() {
const [config, setConfig] = useState(initialObjectConfig)
useEffect(() => {
setConfig(prevWaA => {
...prevWaA,
jsonObject: {
...prevWaA.jsonObject,
newDate = cE
}
})
}, [])
}
You can apply the same thought to a Switch statement but if you don't want to keep state immutability you can take a look at immer.js which is a library that can help you achieve exactly what you are looking for.
Please see my code below.
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
addUser() {
users.push(this.name, this.email)
}
}
const userOne = new User ('John', 'john#mail.com');
const userTwo = new User ("Alan", "alan#mail.com");
let users = [];
userOne.addUser();
userTwo.addUser();
After method addUser i have array with names and emails but i would like to have an array with objects as below
users = [
{ name: 'John', email: 'john#mail.com' }
{ name: 'Alan', email: 'alan#mail.com' }
]
How my method addUser should looks in my prototype and if variable users is in correct place or can be store somewhere in Class?
Thanks in advance
You're pushing the object properties one after the other, rather than as an object together.
Try this for your addUser method:
addUser() {
users.push({name: this.name, email: this.email})
}
You just need to push each proprieties
users.push({name: this.name, email: this.email})
If you want to do this automatically you can use:
users.push(Object.assign({}, this))
Or you cloud just pass the whole object:
users.push(this)
Anyhow, I would suggest not to use users globally.
I have a handleCreate function that takes care of taking some user data and inserting it into a database.
Inside the aliasArr.forEach() loop I POST into my DB new user instances for each element in the aliasArr array. This particular code works as expected, if I check the DB, I will find the new members.
After saving the new members, I want to keep the members in the members array so I can pass it along to another function.
For this, I'm doing members.push(memberAttributes); but if I log the contents of members I get the right amount of elements but the alias property value is duplicated (all other properties should have the same value cause they are being added into the same role in a batch operation).
If I have two new users, say: xyz and abc, I get:
[
{alias: "abc", Role: "admin", "grantedBy": "someone"},
{alias: "abc", Role: "admin", "grantedBy": "someone"},
]
Instead of:
[
{alias: "xyz", Role: "admin", "grantedBy": "someone"},
{alias: "abc", Role: "admin", "grantedBy": "someone"},
]
Here's the code:
handleCreate = () => {
const { memberAttributes } = this.state;
const { role, createRoleMember } = this.props;
const roleArr = [];
roleArr.push(role);
const aliasArr = memberAttributes.alias.split(",");
let members = [];
//false hardcoded during debugging.
if (false /* await aliasIsAdmin(memberAttributes.alias, roleArr) */) {
this.setState({ userExists: true });
} else {
memberAttributes["Granted By"] = window.alias;
memberAttributes.Role = role;
memberAttributes.timestamp = Date.now().toString();
this.handleClose();
aliasArr.forEach((currAlias) => {
memberAttributes.alias = currAlias;
console.log("memberAttributes:", memberAttributes);
members.push(memberAttributes);
console.log("members", members);
const marshalledObj = AWS.DynamoDB.Converter.marshall(memberAttributes);
const params = {
TableName: "xxx",
Item: marshalledObj,
};
axios.post(
"https://xxx.execute-api.us-west-2.amazonaws.com/xxx/xxx",
params
);
});
}
createRoleMember(members); //passing members to this function to do more stuff.
};
I'm wondering if this issue is due to memberAttributes being part of the component's state.
The problem here is that you are pushing references to the same object into the array after changing a value within that object. So whenever you make the change to memberAttributes.alias, it's changing the alias to the most recent one. After that, all references to the same object (which in this case is every item in the members array) present the new value in alias.
const obj = { alias: 'abc', role: 'role1' }
const arr = []
arr.push(obj)
obj.alias = 'new alias'
arr.push(obj)
for (var mem of arr) {
console.log(mem)
}
To fix it, you need to create a new object each time and push it onto the array instead, like so:
aliasArr.forEach((currAlias) => {
// Creates a new object in memory with the same values, but overwrites alias
const newMemberAttributes = Object.assign(memberAttributes, { alias: currAlias });
console.log("memberAttributes:", newMemberAttributes);
members.push(newMemberAttributes);
console.log("members", members);
...
}
Similarly, you can use the spread operator to create a deep copy of the object and then reassign alias.
aliasArr.forEach((currAlias) => {
// Creates a new object in memory with the same values, but overwrites alias
const newMemberAttributes = { ...memberAttributes };
newMemberAttributes.alias = currAlias
console.log("memberAttributes:", newMemberAttributes);
members.push(newMemberAttributes);
console.log("members", members);
...
}
I'm trying to check an object (customer) against another object (developers), there are multiple developers so I have an object which houses all of them and I'm iterating through object that holds the developer, when a customer tests positive for the age condition then a test string is pushed onto the gateKeeper. possibilities property and in turn creates a new customer object from the customer class however, when I run gatekeeper.build(prospect, developers) pass it to a variable and console.log that variable it shows the possibilities properly as undefined, but when I console.log from inside the promise it shows it passed, for both developers, meaning it is pushing 'worked' onto the possibilities property but it isn't using that value when It builds the class, why?
edit
This now does as expected, I replaced the promise chain with a callback chain however as I understand it; the promise syntax paired with async await is the most correct way to execute functions when the timing of execution is important. I think I might be missing something as it regards to promises because code running within the promise chain executes but doesn't seem to affect anything outside the promise chain. If this is the case then (in my limited experience lol) I can't see any use case for the promises or the async await syntax, can someone please help me clarify this?
age: 28,
income: 75,
maritalStatus: 'Married',
majorCc: 'Y',
zipCode: 32805,
possibilities: {}
};
var developers = {
westgate: {
name: 'Westgate',
aTop: 68,
aBot: 28,
income: 50,
majorCc: 'Not Required',
maritalStatus: ['Married', 'Co Hab'],
payload: ['Myrtle Beach', 'Orlando', 'Gatlinburg', 'Cocoa Beach']
},
bluegreen: {
name: 'Bluegreen',
aTop: 999,
aBot: 25,
income: 50,
majorCc: 'Not Required',
maritalStatus: ['Married', 'Single Male', 'Co Hab', 'Single Female'],
payload: ['Myrtle Beach', 'Orlando', 'Gatlinburg', 'Cocoa Beach']
},
};
let gateKeeper = {
prospect: {},
settings: {},
possibilities: [],
methods: {
age(callback1) {
if (gateKeeper.prospect.age >= gateKeeper.settings.aBot && gateKeeper.prospect.age <= gateKeeper.settings.aTop) {
callback1();
}
},
income(callback) {
if (gateKeeper.prospect.income >= gateKeeper.settings.income) {
callback();
}
},
createPayload() {
var cache = {};
cache[gateKeeper.settings.name] = gateKeeper.settings.payload;
gateKeeper.possibilities.push(cache);
},
packageMethods() {
gateKeeper.methods.age(() => {
gateKeeper.methods.income(() => {
gateKeeper.methods.createPayload();
});
});
}
},
resources: class customer {
constructor(prospectInput, developerInput) {
this.age = prospectInput.age;
this.income = prospectInput.income;
this.maritalStatus = prospectInput.maritalStatus;
this.majorCc = prospectInput.majorCc;
this.zipCode = prospectInput.zipCode;
this.possibilities = developerInput; //MUST BE A DICTIONARY WITH ARRAY OF LOCATIONS
}
},
build(prospectInput, developersInput) {
var payload;
gateKeeper.prospect = prospectInput;
for (var i in developersInput) {
gateKeeper.settings = developersInput[i];
payload = gateKeeper.prospect;
gateKeeper.methods.packageMethods();
}
return new gateKeeper.resources(gateKeeper.prospect, gateKeeper.possibilities);
}
};
var test = gateKeeper.build(prospect, developers);
console.log(test.possibilities[1].Bluegreen[3]);
I'm building a deletion process where I need to find out if a certain document is referenced from another documents before deleting the original document.
In the example below, I need to find out if a given Company is used somewhere in my other documents:
Model metadata:
Company = {
id: ID,
name: name
}
User = {
id: ID,
name: name,
company_id: ID
}
Application = {
id: ID,
type: string,
company_id: ID
}
...
Here is what I would do using asynchronous calls:
const checkInUse = async (company_id) => {
let ret = await UserModel.findOne({ company_id: company_id });
if (ret) return true;
ret = await ApplicationModel.findOne({ company_id: company_id });
if (ret) return true;
...
return false;
}
I have some dozen of collections, so some checks would take several calls to findOne(), and that's what I want to avoid.
Is there is a better way of doing this check ?