Karan
Karan

Reputation: 1151

ReactJS looping in render state

im having difficulties with a responsive upvote button. I check for what a user has given upvote to by an array returned from an ajax call called users. Then I loop through that array to see if the post id is matched with any of the elements in that array 'users' That would only imply that they have given that post a "upvote". I have received the ajax calls fine but I map my posts in my render using

render:function() {
   var users = this.props.users;
   var upvoted = this.props.users.upvoted;
   return(
      <div>
      <ul> 
         {
          this.props.posts.map(function(post) {
            //check for array and post id match here
            for ( var i = 0; i < upvoted.length; i++) {
               if(upvoted[i] == post._id){
                console.log("hit upvote! " + post._id);
                var style = { color: 'rgb(0, 255, 0)'};
            }
            else {
                var style = { color : 'rgb(64, 77, 91)'}
                console.log("miss upvote! " + post._id);
            }
         } 
            }
            return(
            <div id = {post._id}>
            //do post stuff here
            <span className = "up arrow" onClick = {updateUpvotesAndArrowColor()} style = {style}></span>
            <p>{post.body}</p>
           </div>
           )
          })
         }
          </ul>
          </div>

However since it is in my render method, it will do the for loop everytime setState is triggered on the array "user". If I have three posts upvoted on my webpage, my user.upvoted array will be filled with those three id's, however it will at the end result only highlight the last element in that upvoted array's upvote button as green.

After logging it in the console here is a example, there are 4posts on the page, 8 total calls I believe (4 before state of users is set, and 4 after I think..)

posts.jsx:207 hit upvote! 559ae6fe236c0e88059cb1ce
posts.jsx:207 miss upvote! 559ae6fe236c0e88059cb1ce
posts.jsx:207 miss upvote! 559ae805f6b34cfc13e998ff
posts.jsx:202 hit upvote! 559ae805f6b34cfc13e998ff
2 posts.jsx:207 miss upvote! 559ae731236c0e88059cb1d0
2 posts.jsx:207 miss upvote! 559ae6ee236c0e88059cb1cd

Here is the upvote json of the user :

upvoted: Array[2]
0: "559ae6fe236c0e88059cb1ce"
1: "559ae805f6b34cfc13e998ff"length: 2

End result only upvoted[1] is highlighted. Is there a better way to check if they are the elements in my user.upvotedP array are upvoted with the mapping function I have?

Upvotes: 0

Views: 200

Answers (1)

Felix Kling
Felix Kling

Reputation: 817128

Your logic is incorrect. You are basically testing whether the last element in the array is equal to the post ID. But that can only be true for a single post.

You could move the else branch before the loop to assume that by default the post is not liked.

However, there is a simpler way to express this logic: Check for the existence of the ID in the array, using indexOf:

var style = {
  color: upvotes.indexOf(post._id) > -1 ? 'rgb(0, 255, 0)' : 'rgb(64, 77, 91)'
};

Upvotes: 2

Related Questions