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);
Related
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);
}
I have a payload which may or may not contain a value.
const { mainValue } = payload;
This mainValue can either only be optionaA or optionB.
I am constructing another object based on this value. How can I conditionally construct the below object. Either I need newProp1 or just newProp2. Is there an ES6 way of doing it, which will be neater.
const newObj = {
propertyA: someValue,
AttributeA: {
newProp1: {
value: optionaA
},
//// i need newProp1 or newProp2 in this newObj
newProp2: {
value: optionaB
}
}
}
I believe the smallest amount of code you can have that will produce the desired output is:
const { mainValue } = payload
const newObj = {
propertyA: someValue,
AttributeA: {
[`newProp${mainValue === optionaA ? 1 : 2`]: {
value: mainValue
}
}
}
The ES6 feature that enables it is Computed Property Names
I have an user object - I want to generate test for each user property and check if it's the right type. However as typeof array is an object assertion fails on array properties with "AssertionError: expected [ 1 ] to be an object".
I have therefore checked if the property is an array and then generate special test for it. I'm wondering if this is the right approach? I have a feeling I'm misssing something obvious.
Object.keys(pureUser).forEach(property =>{
// since typeof array is an object we need to check this case separately or test will fail with expecting array to be an object
if (Array.isArray(pureUser[property])) {
it(`should have property ${property}, type: array`, function () {
user.should.have.property(property);
});
} else {
it(`should have property ${property}, type: ${(typeof pureUser[property])}`, function () {
user.should.have.property(property);
user[property].should.be.a(typeof pureUser[property]);
});
}
});
pureUser is something like this:
let pureUser = {
username: "JohnDoe123",
id: 1,
categories: [1,2,3,4]
}
User variable is defined elsewhere via got.js
change your test to be pureUser[property].should.be.an.Array or user[property].should.be.an.Array
forEach
The forEach() method calls a provided function once for each element in an array, in order.
let pureUser = {
username: "JohnDoe123",
id: 1,
categories: [1,2,3,4]
}
Object.keys(pureUser).forEach(property =>{
// since typeof array is an object we need to check this case separately or test will fail with expecting array to be an object
if (Array.isArray(pureUser[property])) {
console.log('Yes, it\'s an Array')
//it(`should have property ${property}, type: array`, function () {
// user.should.have.property(property);
//});
} else {
console.log('No, it\'s not an Array')
//it(`should have property ${property}, type: ${(typeof property)}`, function () {
//user.should.have.property(property);
// user[property].should.be.a(typeof pureUser[property]);
//});
}
});
When you use forEach on pureUser, the parameter will be the objects properties, like username, id, etc
let pureUser = {
username: "JohnDoe123",
id: 1,
categories: [1,2,3,4]
}
Object.keys(pureUser).forEach(property =>{
console.log(property);
});
You can also access the array in your forEach function.
arr.forEach(item, index, arr)
I have an objects
usersById: {
1: { name: 'John' },
2: { name: 'Michelle' },
...
}
I want to return the same object, but first populate the object at id=2 with a new property age, but sticking to immutability.
I would guess it would be something like
return {
...usersById,
...usersById[2].age = 40
}
but I receive an error In this environment the sources for assign MUST be an object. This error is a performance optimization and not spec compliant.
Alternatively, I would guess it should be something like
return Object.keys(usersById).map(userId => {
if (userId === 2) {
return {
...usersById[2],
...age = 40
}
}
return usersById[userId]
})
but it returns an array and not an object.
You've got the right idea but the wrong syntax. Try this instead:
return {
...usersById,
2: {
...usersById[2],
age: 40
}
}
Or if the key is dynamic, you can do this:
let key = 2;
return {
...usersById,
[key]: {
...usersById[key],
age: 40
}
}
You can make your own function to return same object with populated values
Simple example:
var usersById = {
1: { name: 'John' },
2: { name: 'Michelle' },
}
usersById = oneLevelDeepAssign(usersById,2,{age:21})
function oneLevelDeepAssign(object, key, objectToAssign){
return Object.assign({},object,{[key]:Object.assign({},object[key],objectToAssign)})
}
console.log(usersById);
I'm using a function to filter a JSON file based on the value of the year key, like so:
function filterYr(json, key, value) {
var result = [];
for (var year in json) {
if (json[year][key] === value) {
result.push(json[year]);
}
}
return result;
}
I'm then setting a default:
var chooseYear = filterYr(json, 'year', "2000");
However there's also a dropdown, so the JSON file can be filtered onchange of the dropdown select option.
My question is, can I use this same function to filter the same JSON file by another value, too?
So for instance, I also want to filter by the key 'type.'
If it were a new function it'd be:
function filterType(json, key, value) {
var result = [];
for (var type in json) {
if (json[type][key] === value) {
result.push(json[type]);
}
}
return result;
}
But how do I combine that into one function?
And then how do I set a default that passes both the 'type' and the 'year' to the function?
Is that possible?
Thank you and let me know if I can provide more detail if this isn't clear.
PS- I'd prefer to just use javascript and not a library, if possible.
If your data structure is like below, your current function just works well
var items = [
{
year: 2000,
type: 'type1'
},
{
year: 2001,
type: 'type2'
}
];
function filterYr(json, key, value) {
var result = [];
for (var year in json) {
if (json[year][key] === value) {
result.push(json[year]);
}
}
return result;
}
filterYr(items, 'type', 'type2'); //[ { year: 2001, type: 'type2' } ]
filterYr(items, 'year', 2000); //[ { year: 2000, type: 'type1' } ]
You just need to use a more general name for your function and year variable
You can modify the function so it accepts an object as criterion for filtering. The following function accepts an object with n number of properties:
function findWhere(collection, props) {
var keys = Object.keys(props), // get the object's keys
klen = keys.length; // cache the length of returned array
return collection.filter(function(el) {
// compare the length of the matching properties
// against the length of the passed parameters
// if both are equal, return true
return keys.filter(function(key) {
return el[key] === props[key];
}).length === klen;
})
}
var filteredCollection = findWhere(arrayOfObjects, {
type: 'foo',
anotherProp: 'aValue'
});