How can I delete the proper object property value in JS - javascript

I am working through a little practice assignment and have come across this question and for the life of me can't figure it out.
There are tests parameters that I can't see. The object is not a variable I can see, it's just assumed.
Write a function called removePassword that takes in an object.
Delete the property password and return the object.
removePassword=(object)=>{
for(var key in object){
if(object = object[key]){
delete object[key]
}
}return object;
}
I have tried a bunch of different versions of this code, but I don't know how to just delete the property password only without deleting the other property which is a username

Take a look at this solution. You can avoid doing the object copy if you want, it'll work anyway
const removePassword = (user) => {
const userCopy = {...user} // CREATE A COPY OF THE OBJECT
delete userCopy.password // DELETE THE PASSWORD PROPERTY
return userCopy // RETURN UPDATED USER
}
const testUser = {username: 'Mario', password: 'supersecret123'}
console.log(
removePassword(testUser)
)

Could it work for you?
removePassword = (object) => {
delete object.password;
return object;
}

You can see here link
That you can do it simply delete object.password or delete object["password"] :
const removePassword = (object) => {
delete object.password;
return object;
}

Related

How to update an item in an array of an object

I have a list of people, each with an id. I have to add a tag to a newly created array for a person with a certain id. The json object 'students' already exists and I am updating it using its useState setStudents method but it seems to be returning an unidentified object back. My plan was as follows:
Map through the previousStudents
If the id matches (the person who I'm adding a tag to), then add the tag. The if statement to add a tag is there because the 'tags' property doesn't initially exist, so I make it on the first tag add
If the id doesn't match, just return that student
const updateStudent = (tag, id) => {
setStudents((prevStudents) => {
prevStudents.map((student) => {
if (student.id !== id) return student;
if (student.tags) {
student["tags"].push(tag);
} else {
student["tags"] = [tag];
}
return student;
});
});
};
Sorry if my explanation was confusing but tldr: I'm just trying to add an item to an array of a specified object and it doesn't seem to be working.
A "cleaner" approach would be something like this:
const updateStudent = (tag, id) => {
// form a new students object
let newStudents = students.map(student => {
if(student.id === id) {
student.tags? student.tags.push(tag) : student.tags = [tag];
}
return student;
});
setStudents(newStudents); // set the newly formed object to state
}
It is better to separate the update logic from setting the state

How to delete key:value pair from req.user object

Why does the delete operator on the req.user object not work?
let test = new Object(req.user);
console.log(test.password); // Get correct string
delete test.password;
console.log(test.password); // Get correct string, but expect undefined
This works for me
let test = {user:"hello", password:"goodbye"};
console.log(test.password);
// output is: hello
delete test.password;
console.log(test.password);
// output is: undefined
Could you edit post a snippet with an explicit assignment at the top (rather than a reference to req.user, which we can't reproduce). See if the problem reproduces with that.
Use new Object() on an existing object, doesn't actually create a new object. All you get is a reference to the original one.
The original object (req.user) might have the password field as part of it's prototype, and not as an own property. Deleting it from the object does nothing, because it's not a part of the object.
Demo:
const base = Object.create({user:"hello", password:"goodbye"});
const test = new Object(base);
console.log(test === base); // true - it's the same object
console.log({ pass: test.password, ownProp: test.hasOwnProperty('password') });
delete test.password;
console.log({ pass: test.password, ownProp: test.hasOwnProperty('password') });
This line just creates a reference to an existing object:
let test = new Object(req.user);
It's the same thing as
let test = req.user;
So whether or not you can delete test.password depends on whether or not you can delete req.user.password (it's the same operation). If req.user.password is not a writable property, you will get the behavior you describe.
const req = {
user: {}
};
Object.defineProperty(req.user, "password", {
value: "123456",
writable: false
});
let test = new Object(req.user);
console.log(test.password); // Get correct string
delete test.password;
console.log(test.password); // Get correct string, but expect undefined
const req2 = {
user: {
password: "123456"
}
};
let test2 = new Object(req2.user);
console.log(test2.password); // Get correct string
delete test2.password;
console.log(test2.password); // This works as expected

React Native - Manage CheckBox states

I want to make a Quiz App.
Questions are checked after user presses Submit button.
So questions are checked all at once in the end.
I need to save user choices (answers) for each question and then later check them on submit.
I was thinking about this:
let [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
let [userAnswers, setUserAnswers] = useState([] as any);
function answerClick(value: any, key: any) {
// console.log('answer clicked');
userAnswers[currentQuestionIndex][key] = value;
// TypeError: undefined is not an object (evaluating 'userAnswers[currentQuestionIndex][key] = value')
}
My checkbox for each possible answer in the question:
<BouncyCheckbox
key={index}
onPress={(value) => {
answerClick(value, index);
}}
text={answer.title}
/>
But I get
TypeError: undefined is not an object (evaluating 'userAnswers[current][key] = value')
on Answer click
What is setUserAnswers() equivalent of userAnswers[currentQuestionIndex][key] = value?
Why am I getting undefined error?
How to do this, please help my head hurts.
You are attempting to access a non existing index in the array.
userAnsqers = [];
currentQuestionIndex = 0;
// userAnswers[currentQuestionIndex] === undefined
What are you attempting to do is adding an {} to the array lazily (only when needed). This will work:
function answerClick(value: any, key: any) {
setUserAnswers(latest => {
const out = [...latest];
while (out.length <= currentQuestionIndex) out.push({});
out[currentQuestionIndex][key] = value;
return out;
})
}
There is nothing equivalent to setUserAnswers() for userAnswers[currentQuestionIndex][key] = value (see). You may find som custom hooks to manage arrays or build your own.
First off, the userAnswers should have the key and values of everything you're trying to change. The reason you're getting undefined is because you're trying to target an object in the userAnswers array which can't be found. Also, you are modifying the userAnswers state directly and that's really wrong. That's what the setUserAnswers is for. You can do this instead.
function answerClick(value: any, key: any) {
// console.log('answer clicked');
setUserAnswers([
...usersAnswers,
{[key]: [value]}
]);
}

Angular - Create property in new property of object

Currently, I have a select element in my html which has a ngModel to the object details:
[ngModel]="details?.publicInformation?.firstname"
However, publicInformation may not exist in that object, or if it does, maybe firstname does not exist. No matter the case, in the end, I want to create the following:
[ngModel]="details?.publicInformation?.firstname" (ngModelChange)="details['publicInformation']['firstname'] = $event"
Basically, if the select is triggered, even if neither of publicInformation nor firstname exist, I would like to create them inside details and store the value from the select.
The issue is that I am getting
Cannot set property 'firstname' of undefined
Can someone explain what I am doing wrong here and how can I achieve the result I desire?
You need to initialize details and publicInformation to empty object
public details = {publicInformation : {}};
You should do that when you load the form data.
For example, you might have something like this:
ngOnInit() {
this._someService.loadForm().then((formData: FormData) => {
this.details = formData;
});
}
Then, you could modify that to fill in the missing empty properties you need:
ngOnInit() {
this._someService.loadForm().then((formData: FormData) => {
this.details = formData || {};
if (!this.details.publicInformation) {
this.details.publicInformation = { firstname: '' };
} else if (!this.details.publicInformation.firstname) {
this.details.publicInformation.firstname = '';
}
});
}
However, it would be better to place this logic in the services, so that they are responsible for adding all the necessary empty properties to the data they load, or if you are using Redux, then it should go into the reducers.

How to pass by value and not by reference in React?

I have the following file, LookupPage.jsx and AccountDetails.jsx.
In LookUp
this.updateCustomer = (customer) => {
if(JSON.stringify(customer.address) !== JSON.stringify(this.state.activeAccount.customer.address)) {
console.log('address changed');
customer.update_address = true;
customer.address.source = 'user';
}
return fetch(
`${API_ENDPOINT}/customer/${customer.id}/`,
{
method: 'PATCH',
headers: {
'Authorization': 'Token ' + this.props.session_token,
'Content-Type': 'application/json',
},
body: JSON.stringify(customer),
}
).then(restJSONResponseToPromise).then(responseJSON => {
if(responseJSON.results){
console.log('update customers client side.')
}
}, clearSessionIfInvalidToken(this.props.clearSession));
};
<AccountsDetailModal
show={this.state.showAccountDetail}
close={this.toggleAccountDetail}
customer={this.state.activeAccount.customer}
updateCustomer={this.updateCustomer}
/>
In side AccountDetails
this.onChangeAddress = (e) => {
const customer = {...this.state.customer};
const address = customer.address;
address[e.target.name] = e.target.value;
customer.address = address;
this.setState({customer, errors: {
...this.state.errors,
[e.target.name]: [],
}});
};
this.saveCustomer = () => {
this.setState({postDisable: true});
const errors = this.getFormErrors();
const hasErrors = !every(errors, (item) => !item.length);
if(!hasErrors){
this.props.updateCustomer(this.state.customer);
} else {
sweetAlert('Error!', 'Form is invalid.', 'error');
}
this.setState({postDisable: false});
};
this.componentDidMount = () => {
this.setState({customer: this.props.customer});
}
When I am updating the customers address, it is updating active accounts address, so it seems like it is being passed by reference. What I want to happen is only update the customer address if the address was changed/different from the original. How would I modify my code to do this?
You can pass any object by value in JS (whether you're using React or not) by passing:
JSON.parse(JSON.stringify(myObject))
as an argument instead of the object itself.
Essentially this will just clone the object and pass a copy of it, so you can manipulate the copy all you want without affecting the original.
Note that this will not work if the object contains functions, it will only copy the properties. (In your example this should be fine.)
I am going to put my two cents here:
First of all, this isn't really specific to React and is more of a JS related question.
Secondly, setting props against internal state is considered to be a bad practice when it comes to react. There's really no need to do that given your particular scenario. I am referring to
this.setState({customer: this.props.customer});
So, coming to your problem, the reason you are having reference issues is because you are mutating the original passed in object at certain points in your code. For instance, if I look at:
this.updateCustomer = (customer) => {
if(JSON.stringify(customer.address) !== JSON.stringify(this.state.activeAccount.customer.address)) {
console.log('address changed');
customer.update_address = true;
customer.address.source = 'user';
}
};
You are mutating the original props of the argument object which is very likely to be passed around in other methods of your component. So, to overcome that you can do:
const updatedCustomer = Object.assign({}, customer, {
update_address: true
});
And you can pass in updatedCustomer in your API call. Object.assign() will not perform operation on the passed in object but will return a new object so you can be sure that at any point in your app you are not mutating the original object.
Note: Object.assign would work on plain object and not a nested one. So, if you want to achieve something similar that would work on nested object properties too, you can use lodash merge.

Categories