How to print out only object values that are true? - javascript

I am learning Javascript, and am making a simple user verification object. I need a function that will console.log only users who have "isVerified" set to true.
I have tried numerous ways including loops and if statements. The function name is "showVerified" below.
var person = {
info: [],
displayPerson: function() {
console.log('People', this.info);
},
addPerson: function(age, firstName, lastName) {
this.info.push({
age: age,
firstName: firstName,
lastName: lastName,
isVerified: false
});
this.displayPerson();
},
deletePerson: function(position) {
this.info.splice(position, 1);
this.displayPerson();
},
verifyPerson: function(position) {
this.info[position].isVerified = true;
this.info[position].firstName = this.info[position].firstName.toUpperCase();
this.displayPerson();
},
showVerified: function() {
for (var key in this.info) {
if (this.info.isVerified = true) {
console.log(this.info.isVerified[key]);
}
}
}
}
What I want to happen when running showVerified on my person object, is for it to print out ONLY the age, first name, and last name of any person who is verified.

I suggest trying to change the way you're naming your properties, so the code is a bit clearer.
Try
showVerified: function() {
this.info.filter(x => x.isVerified).forEach(v => console.log(v))
}

if you don't want to use filter, you can try this as well
this.info.forEach(person => {
if(person.isVerified){
console.log(person);
}
});

Related

Check object variable exists when using object destructuring

I have a 'getData' function which gets passed a 'data' variable. Inside the function I'm trying to access an object 'data.someObject' which may or may not exist because it comes from an outside library.
What is the best approach to check if it does exist before trying to use it? Also see I'm using object destructuring here aswell.
const getData = (data) => {
const { name, age } = data.someObject; // someObject may or may not exist
console.log(name, age);
}
I thought doing this might work:
const { name, age } = data.someObject || {};
But I wasn't sure if that would throw an error.
Thanks
You can use || & if required provide default values while destructuring.
function print(user) {
const { fname = "Anonymous", lname = "Panda" } = user.fullname || {};
console.log(`Hello ${fname} ${lname}`);
}
print({ fullname: { fname: "John", lname: "Doe" } });
print({});
print({ fullname: null });
Personally I would put an if statement:
const getData = (data) => {
if (data.someObject == null) {
// Here you can return, throw an error or do anything else you might need
}
const { name, age } = data.someObject; // someObject may or may not exist
console.log(name, age);
}

Simplify nested for loop

I have this code:
let peopleInRoom = [];
for (let message of messages) {
for (let email of message.user.email) {
if (!peopleInRoom.includes(email)) {
peopleInRoom.push(email);
}
}
}
let peopleInRoomElement = peopleInRoom.map(person => (
<li>{person}</li>
))
Basically I am trying to get all the unique emails and display them.
Is there a shorter and more efficient way (maybe some ES6 features) to write the same code? Seems too much code than needed.
I looked at this answer: How to get distinct values from an array of objects in JavaScript?
EDIT: Above code does not do what I want.
My data looks like this:
[
{
text: 'foo',
user: { email: 'foo#bar.com', password: 'foo' }
},
{
text: 'baz',
user: { email: 'baz#qux.com', password: 'baz' }
}
]
The objects are all messages. And I want to get an array of all the unique emails from each message
You can use the Set object that is built into JavaScript. Set object actually keep the distinct primitive values.
const messages = [
{
text: 'foo',
user: { email: 'foo#bar.com', password: 'foo' }
},
{
text: 'baz',
user: { email: 'baz#qux.com', password: 'baz' }
}
]
const peopleInRoom = [...new Set(messages.map(message => message.user.email))];
It actually extracts the email from each message and then passes it to the Set object which only keeps the unique set of emails. After that, it will spread that Set to the array, since Set is also an iterable and returns the array of the people in room.
If I understand correctly, people have messages, messages have email addresses and the OP seeks the unique set of email addresses. If that's all the data available, then there's no alternative but to iterate it, checking to see if each email has been collected already, and collecting it if it hasn't been.
There are ways to conceal this work by doing it in library code. Probably the highest level utility is lodash's _.uniqueBy, but the work must be done one way or another.
The Set object enforces uniqueness of its elements. You can use it this way:
const peopleInRoom = Array.from(new Set(messages.map(message => message.user.email)));
First you can make an array of all the email addresses:
const data = [
{
text: 'foo',
user: { email: 'foo#bar.com', password: 'foo' }
},
{
text: 'baz',
user: { email: 'baz#qux.com', password: 'baz' }
}
]
const emailArray = data.map((elem) => {
return elem.user.email;
}
and then you can filter them to be unique:
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
emailArrayFiltered = emailArray.filter(onlyUnique);
see here for ref link
What about:
const peopleInRoom = messages.map(e => e.user.email && e.user.email);
console.log(peopleInRoom)
gives you this output:
["foo#bar.com", "baz#qux.com"]

How to load mobx state from json?

I want to store my mobx state in browser localStorage, so, if i use this approach https://stackoverflow.com/a/40326316
I save store with toJS, but don't know how to apply it. With extendObservable I get following error Error: [mobx] 'extendObservable' can only be used to introduce new properties. Use 'set' or 'decorate' instead
Thanks in advance.
My approach is:
class MyStore {
...
public async load() {
const cached = await browser.storage.local.get("cache");
const data = JSON.parse(cached["cached"]);
Object.keys(data).forEach(x => {
(this as any)[x] = (data as any)[x];
});
...
}
But i think this is anitpattern.
Are you sure extendObservable doesn't work.
I've used something like this in my code.
class MyStore {
async load() {
const cached = await browser.storage.local.get("cache");
mobx.extendObservable(this, cached);
}
}
Edit:
This seems to be not working, you need to access the properties after extendObservable in order to reload them, you could use autorun but just use another method.
I've implemented load function based on a simple forEach;
Try the following.
load = async () => {
const { cache } = await JSON.parse(localStorage.getItem("cache"));
Object.keys(cache).forEach(key => {
this[key] = cache[key];
});
};
CodeSandbox
https://codesandbox.io/s/late-snow-xppx0?ontsize=14&hidenavigation=1&theme=dark
If you have a class, and "raw" json data, what i'm doing is to accept raw data in the constructor & then update the class properties.
For example, my raw data looks like this:
{
users: [
{ id: 1, firstName: 'foo', lastName: 'bar', customer: { id: 1, name: 'bla' } },
{ id: 2, firstName: 'foo2', lastName: 'bar2', customer: { id: 2, name: 'customer' } },
];
}
class User {
id;
#observable firstName;
#observable lastName;
customer;
constructor(rawUser) {
this.id = rawUser.id;
this.firstName = rawUser.firstName;
this.lastName = rawUser.lastName;
this.customer = new Customer(rawUser.customer);
}
}
class UsersStore {
#observable users = [];
constructor(rawUsers) {
this.users = rawUsers.map(rawUser => new User(rawUser));
}
}
Then when I'm restoring the data I'm just using
const usersStore = new UsersStore(rawData.users);
The cool thing in this approach is the nesting handling, each "level" handles its part.

Javascript objects keys without value

I am following the redux tutorial https://redux.js.org/basics/actions and having a hard time understanding the following code
export function addTodo(text) {
return { type: ADD_TODO, text }
}
So the function above returns the object { type: ADD_TODO, text } and there are two things that confuse me.
what is the value of this object associated with the key text. If this value is undefined, then why not just return { type: ADD_TODO} instead.
If text is a string, then shouldn't it be { type: ADD_TODO, [text]: *some value* } instead?
Moreover, there are other functions like
function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
function setVisibilityFilter(filter) {
return { type: SET_VISIBILITY_FILTER, filter }
}
Can someone explain this syntax to me?
They're using ES6 Shorthand property names - If the intended key name is the same as the variable, then you can simply pass the variable
let name = 'Jared';
let age = 19;
let literate = false;
let obj = {
name,
age,
literate
}
/* Is the same as...
let obj = {
'name': name,
'age': age,
'literate': literate
}
*/
console.log(obj);

Javascript For...In syntax issue?

The search function in the following code is not working and I believe it has something to do with the For...In loop but I am new to JS and unsure why:
var friends = {
bill: {
firstName: "bill",
lastName: "smith",
number: 1,
address: ["1"]
},
steve: {
firstName: "steve",
lastName: "smith",
number: 2,
address: ["2"]
}
};
var list = function(list) {
for(var item in list) {
console.log(item);
}
};
var search = function(name) {
for(var friend in friends) {
if(friend.firstName === name) {
console.log(friend);
return friend;
}
}
};
search("steve");
The for in loop iterates over keys, not values.
friend is a string holding the name of each property.
To get the value, use friends[friend].
Great documentation of the for..in loop can be found on mdn. Where variable is assigned through each iteration to "a different property name".
You also may not need to loop through each friend. What if you changed your search function to use hasOwnProperty on the object:
var search = function(name) {
if(friends.hasOwnProperty(name)){
return friends[name];
}
};
This would check that you have a property of name in the object friends and return it. Here's a quick EXAMPLE.

Categories