Reputation: 1013
Im trying to filter out objects with a delete: false
to then only map and render this objects to screen but I'm not sure how to get it to work.
Sample object
{
"8xf0y6ziyjabvozdd253nd": {
"id": "8xf0y6ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}
Method for finding key and map.
const {posts} = this.props
return _.find(posts, { 'deleted': false })_.map(posts, post => {
return (
<div key={post.id}>
Upvotes: 7
Views: 26868
Reputation: 4175
Basically, you can apply lodash#reduce to Object directly instead of getting all the keys first, and then iterating again. And with reduce
you can do the map and filtering together.
_.reduce(obj, (i, v, k)=> !v.deleted && !(i[k] = v) || i, {});
Let's create a working example for you, Here is a code snippet:
var obj = {
"9ny0z4ziyjabvozdc713dr": {
"id": "9ny0z4ziyjabvozdc713dr",
"timestamp": 1467166879723,
"title": "StackOverfow is the best place to learn Angular",
"body": "bla bla bla bla.",
"author": "myself",
"category": "angular",
"voteScore": 9,
"deleted": true
},
"8xf0y6ziyjabvozdd253nd": {
"id": "8xf0y6ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}
var finalObj =_.reduce(obj, (i, v, k)=> !v.deleted && !(i[k] = v) || i, {});
console.log(finalObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
EDIT
For the specific case (of OP), just some key/value pair needs to be removed and construct a new object, then better to use lodash#omitBy to simply remove some entries from an object against some condition. Here is a simple example of this particular use.
_.omitBy(obj, o=>o.deleted);
Here is the code snippet for this example:
var obj = {
"9ny0z4ziyjabvozdc713dr": {
"id": "9ny0z4ziyjabvozdc713dr",
"timestamp": 1467166879723,
"title": "StackOverfow is the best place to learn Angular",
"body": "bla bla bla bla.",
"author": "myself",
"category": "angular",
"voteScore": 9,
"deleted": true
},
"8xf0y6ziyjabvozdd253nd": {
"id": "8xf0y6ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}
var finalObj =_.omitBy(obj, o=>o.deleted);
console.log(finalObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
However, If any transformation needed in between (Array or Object), or the output type needs to be customized then I will still prefer to suggest to use reduce.
Upvotes: 8
Reputation: 1562
If you want to skip lodash
, the native API of javascript array will offer you a solution like the following:
const { posts } = this.props;
return posts
.find(post => !post.deleted)
.map(post => {
return (
<div key={post.id}>...
Upvotes: 1
Reputation: 662
If you want to filter, the easiest thing to use is an actual filter. I'm not very familiar with React, but the Lodash chain below will work, if React supports more complex chains.
I noticed you have a nested object, if that is intentional, then the code below will do the trick:
// I added some fake posts to make the data more illustrative
let posts = [{
"8xf0y6ziyjabvozdd253nd": {
"id": "8xf0y6ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}, {
"8888ziyjabvozdd253nd": {
"id": "8888ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": true
}
}, {
"77776ziyjabvozdd253nd": {
"id": "77776ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}, {
"6666ziyjabvozdd253nd": {
"id": "6666ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": true
}
}, {
"55556ziyjabvozdd253nd": {
"id": "55556ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}];
// you'd just return _(posts) here directly, but I'm assigning a variable so we can show the console log for this snippet
const filteredPosts = _(posts)
.filter(post => {
const objectKey = Object.keys(post)[0];
const innerData = post[objectKey];
return innerData.deleted === false
})
.map(post => {
const objectKey = Object.keys(post)[0];
// your return would be in the format of <div key={objectKey}>
return `<div key={${objectKey}}>`
})
.valueOf();
console.log(filteredPosts);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
If the nesting of the object isn't intentional, then getting the info will be more straightforward and cleaner. If your actual objects look like the sample ones I have below, you could access the data like this:
let posts = [{
"id": "8xf0y6ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}, {
"id": "8888ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": true
}, {
"id": "77776ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}];
// you'd just return _(posts) here directly, but I'm assigning a variable so we can show the console log for this snippet
const filteredPosts = _(posts)
.filter(post => {
return post.deleted === false
})
.map(post => {
// your return would be in the format of <div key={post.id}>
return `<div key={${post.id}}>`
})
.valueOf();
console.log(filteredPosts);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Upvotes: 2
Reputation: 10458
you can do that in the following way
let obj = {
"8xf0y6ziyjabvozdd253nd": {
"id": "8xf0y6ziyjabvozdd253nd",
"timestamp": 1467166872634,
"title": "Udacity is the best place to learn React",
"body": "Everyone says so after all.",
"author": "thingtwo",
"category": "react",
"voteScore": 6,
"deleted": false
}
}
let result = Object.keys(obj).reduce((a, b) =>{
if(obj[b].deleted != false){
a[b] = obj[b];
}
return a;
}, {});
console.log(result);
Upvotes: 0
Reputation: 62556
The result of _.find
is an array, so if you want to map
the elements in that array you should _.map(result)
const {posts} = this.props;
return _.map(_.find(posts, { 'deleted': false }), post => {
return (
<div key={post.id}>
Upvotes: 1