Paulos3000
Paulos3000

Reputation: 3545

Filtering array elements in React/Redux

I have a React application which filters users and posts. My navbar can link to either users, posts.

Clicking on posts brings up a list of every post made, by all users (with some extra meta information for each one).

Here is my Posts component:

export default class Posts extends Component {
   render() {
      return (
         <div>
            {this.props.posts.map( post =>
               <Post {...this.props} post={post} key={post.id} />
            )}
         </div>
      )
   }
}

On the users page, each user has a sublink posts. What I want is to be able to click on posts for that user and it to take you to a posts page (like above), but only list the posts for that user.

The posts array looks a bit like this:

[
  { id: 1,
   userId: 1 
  },
  { id: 2,
   userId: 1 
  },
  { id: 3,
   userId: 2 
  },
  { id: 4,
   userId: 3 
  },
  { id: 5,
   userId: 3 
  }
]

Say I clicked on the user with userId of 3, and only wanted to display his/her posts. What is the best way to do this?

I know I can use react-router to pass the userId to the URL, and then pull that back into the component, but I'm not sure how to use this once the Posts component renders. Ultimately I want it to render the posts array filtered to the userId route param, else render all posts. Is this right approach?

Any help appreciated.


UPDATE:

Ok, I know this is not an elegant solution, but I want to start off with a solution, then I will 'trim it down', so to speak.

There's a bug in this code which I cannot figure out:

   render() {

      const {userId} = this.props.params

      if(userId) {
         const postsForUser = posts.filter( post => post.userId === userId )
         return (
            <div>
               {postsForUser.map( post =>
                  <Post {...this.props} post={post} key={post.id} />
               )}
            </div>
         )
      }
      else {
         return (
            <div>
               {this.props.posts.map( post =>
                  <Post {...this.props} post={post} key={post.id} />
               )}
            </div>
         )
      }

   } // end render()

When I log userId, it correctly logs the user id that I have just clicked on, so my this.props.params.userId variable is working correctly.

If I define postsForUser with a hardcoded integer, e.g.

const postsForUser = posts.filter( post => post.userId === 3 )

It returns the filtered array correctly.

So at this point it seems everything is working fine, except when I swap out the hardcoded id for the variable, postsForUser returns as an empty array.

Where am I going wrong?


UPDATE 2 (Fix):

For anyone facing this problem, I incorrectly returned the id from this.props.params.userId as a string, so instead I had to define it using parseInt() like this:

const userId = parseInt(this.props.params.userId)

Upvotes: 0

Views: 1692

Answers (1)

narvoxx
narvoxx

Reputation: 807

You can simply use Array's filter method:

render(){
    return (
        <div>
            {
                if(this.params.userId) {
                    const postsForUser = posts.filter(post => post.userId == this.params.userId);
                    //renderPostList(postsForUser)
                } else {
                    //renderPostList(posts)
                }
            }
        </div>
    )
}

Upvotes: 1

Related Questions