Reputation: 611
I have three different arrays. Posts, Categories and Tags. I want to get values from Categories and Tags and merge it with it's Post in the Posts array. Hopefully my code will make it clear what I am trying to achieve.
So after all is done, I am returned a new array with my _.merged data but all the values are undefined. I can't figure out what I am doing wrong here. I'm sure it's a simple mistake I am making.
Posts array
[
{
"id": 79,
"slug": "checkbox-code",
"type": "post",
"title": {
"rendered": "Checkbox code"
},
"categories": [
6
],
"tags": [
7
],
},
{
"id": 77,
"slug": "checkbox-style",
"type": "post",
"title": {
"rendered": "Checkbox style"
},
"categories": [
6
],
"tags": [
8
],
},
{
"id": 75,
"slug": "checkbox-usage",
"title": {
"rendered": "Checkbox usage"
},
"categories": [
6
],
"tags": [
9
],
},
]
Categories array
[
{
"id": 6,
"name": "checkbox",
"slug": "checkbox",
"taxonomy": "category",
},
{
"id": 5,
"name": "buttons",
"slug": "buttons",
"taxonomy": "category"
}
]
Tags array
[
{
"id": 7,
"name": "code",
"slug": "code",
"taxonomy": "post_tag",
},
{
"id": 8,
"name": "style",
"slug": "style",
"taxonomy": "post_tag",
},
{
"id": 9,
"name": "usage",
"slug": "usage",
"taxonomy": "post_tag",
}
]
My Code
getTagName = (id) => {
this.tags.map(tag => {
if(id == tag.id) {console.log('tag name ' + tag.name)}
return id == tag.id ? tag.name : null
})
}
getCatName = (id) => {
this.cats.map(cat => {
if(id == cat.id) {console.log('category name ' + cat.slug)}
return id == cat.id ? cat.slug : null
})
}
componentWillMount() {
let arr = [];
for(let i=0; i<this.posts.length; i++) {
let tagName = this.getTagName(this.posts[i].tags[0]);
let catName = this.getCatName(this.posts[i].categories[0]);
let newObj = {
"tag_name": tagName,
"category_name": catName
}
_.merge(this.posts[i], newObj);
arr.push(this.posts[i]);
}
}
What I get back
[
{
"id": 79,
"slug": "checkbox-code",
"type": "post",
"title": {
"rendered": "Checkbox code"
},
"categories": [
6
],
"category_name": undefined,
"tag_name": undefined,
"tags": [
7
],
},
{
"id": 77,
"slug": "checkbox-style",
"type": "post",
"title": {
"rendered": "Checkbox style"
},
"categories": [
6
],
"category_name": undefined,
"tag_name": undefined,
"tags": [
8
],
},
{
"id": 75,
"slug": "checkbox-usage",
"title": {
"rendered": "Checkbox usage"
},
"categories": [
6
],
"category_name": undefined,
"tag_name": undefined,
"tags": [
9
],
},
]
when I log the returned values in the getCatName and getTagName methods I get back the correct data. It just doesn't make it to componentWillMount. Thanks for any help.
Here is a fiddle
Upvotes: 0
Views: 45
Reputation: 375
I think your problem is in your getTagName & getCatName functions...
First, functions are not returning any value out of they own scope
getCatName = (id) => {
return cats.map(cat => {
if(id == cat.id) {console.log('category name ' + cat.slug)}
return id == cat.id ? cat.slug : null
})
}
But remember, map iterates over all the array length, so it will return full sized array, with matches only on certain indexes, like this:
tag_name: (3) […] 0: "code", 1: null, 2: null, length: 3
So maybe you want to change the map for a filter, or work with your mapped data before the return
Hope it helps!
Upvotes: 0
Reputation: 4596
getTagName
and getCatName
don't return anything, so tagName
and catName
will be undefined.
The return
statement in getTagName
belongs to the function you passed to map
(tag => {}
). It doesn't make the outer function (id => {}
) return.
Looks like you're expecting it to work like a for
loop, where the return
would stop the loop early and return tag.name
. map
doesn't work like that, it always iterates over the whole array, and returns a new array the same length. If you added a return statement into getTagName
and called getTagName(8)
, you would get [ null, 'style', null ]
- that's the result of the inner function for each item in the array.
The method you want to use is Array.find
.
getTagName = id => {
return this.tags.find( tag => tag.id === id ).name;
}
Upvotes: 2
Reputation: 3253
the .map() in your getTagName() and getCatName() functions do not really make sense. If you look for a specific Entry it makes sense to use Array.find().
Also you need to return the value. I updated your jsfiddle. https://jsfiddle.net/3pLj20nd/14/
getTagName = (id) => {
return tags.find(tag => {
return id == tag.id;
})
}
getCatName = (id) => {
return cats.find(cat => {
return id == cat.id;
})
}
componentWillMount = () => {
let arr = [];
for(let i=0; i<posts.length; i++) {
let tagName = getTagName(posts[i].tags[0]).name;
let catName = getCatName(posts[i].categories[0]).name;
let newObj = {
"tag_name": tagName,
"category_name": catName
}
console.log(newObj);
_.merge(posts[i], newObj);
arr.push(posts[i]);
}
console.log(arr);
}
componentWillMount();
Upvotes: 1
Reputation: 14165
The return statements in both methods are returning from the Array.map() method. You are not returning a value from your getTagName()
or getCatName()
functions.
Keep in mind that if you return the results of the map method (ie. return this.cats.map(...)
), those results will be in the form of an array.
Upvotes: 2