SupraCoder
SupraCoder

Reputation: 95

My buttons are all attached together via state

I am currently working on a liking feature for posts, as well as replies and shares. Whenever I hit like or reply on one post, all other posts also get highlighted - how can I fix this so only the post that i like gets liked versus all posts getting liked?

My code in question:

<InfiniteScroll height='100%' dataLength={numberOfPosts.length} next={fetchMoreData} hasMore={hasMore} loader={<Loading style={{position: 'absolute', left: '50%'}}/>}
       id='all-post-container' scrollThreshold={0.5} endMessage={<p style={{ textAlign: "center" }}>
       <b>That's all folks!</b>
     </p>}
       style={{position: 'absolute', top: '25%', left: '20%', backgroundColor: '#F7F9FE', height: '72%', width: "54%", borderRadius: '30px'}}>
      <Grid
        container
        direction="column"
        justifyContent="center"
        alignItems="center"
        spacing={45}
      >
      {numberOfPosts.map((key, i) => {
      return (
        <Grid container item>
        <div id="post-container" style={{margin: '5%', position: 'absolute', width: '90%', height: '40%', backgroundColor: 'white', borderRadius: '30px', overflow: 'auto'}}>
          <Avatar src={<AvatarPicture/>} style={{position: 'absolute', left: '1%', top: '3%', height: '60px', width: '60px'}} size='lg'></Avatar>
          <p style={{position: 'absolute', left: '9%', top: '-5%', fontFamily: 'Outfit', fontStyle: 'normal', fontWeight: '500', fontSize: '20px', lineHeight: '25px', overflow: 'auto'}}>@{state.posts[i].username}</p>
          <p style={{position: 'absolute', left: '9%', top: '10%', fontFamily: 'Outfit', fontStyle: 'normal', fontWeight: '400', fontSize: '16px', lineHeight: '20px', color: '#6D7683'}}>{state.storage.location}</p>
          <p style={{position: 'absolute', left: '20%', top: '10%', fontFamily: 'Outfit', fontStyle: 'normal', fontWeight: '400', fontSize: '16px', lineHeight: '20px', color: '#2D87FF'}}>{state.posts[i].date}</p>
          <div id="text-container" style={{position: 'absolute', top: '30%', left: '5%', backgroundColor: '#FFFBEE', height: '30%', width: '90%', borderRadius: '16px', overflow: 'scroll'}}><p style={{position: 'absolute', top: '20%', left: '50%'}}>{state.posts[i].text}</p></div>
          <TextField InputProps={{
            startAdornment: (
              <InputAdornment>
                <Avatar src={state.storage.profileImageURL} />
              </InputAdornment>
            ),
            classes: {
              notchedOutline: 'notched-outline-border-radius'
          }
          }} maxRows={10} inputProps={{maxLength: 500}} multiline style={{position: 'absolute', left: '5%', top: '78%', width: '90%', background: '#F8FAFF', border: '1px solid #D9E1F9', borderRadius: '16px'}} placeholder='Write your comment'></TextField>
          <IconButton onClick={() => setLike(!like)} style={{ position: 'absolute', top: '60%', left: '5%'}} onMouseLeave={() => setMouseOver(false)} onMouseOver={() => setMouseOver(true)}>{like && mouseOver ? <HeartBrokenIcon style={{color: 'red'}}/> : like ? <FavoriteIcon style={{color: 'red'}} /> : <FavoriteBorderTwoToneIcon /> }</IconButton>
          <p style={{position: 'absolute', top: '59%', left: '9%'}}>{state.posts[i].likes}</p>
          <IconButton onClick={() => setReply(!reply)} style={{ position: 'absolute', top: '60%', left: '13%'}}>{reply ? <MessageIcon color="primary"/> : <MessageOutlinedIcon/>}</IconButton>
          <p style={{position: 'absolute', top: '59%', left: '17%'}}>{state.posts[i].comments}</p>
          <IconButton style={{ position: 'absolute', top: '60%', left: '23%'}}><IosShareOutlinedIcon /></IconButton>
          <p style={{position: 'absolute', top: '59%', left: '27%'}}>{state.posts[i].shares}</p>
        </div>
        </Grid>
      )})}
      </Grid>
      </InfiniteScroll> : <div id='content-loader' style={{position: 'absolute', top: '25%', left: '20%', backgroundColor: '#F7F9FE', height: '72%', width: "54%", borderRadius: '30px'}}><Loading size='lg' style={{position: 'absolute', left: '50%', top: '50%'}}/></div>}

Upvotes: 0

Views: 42

Answers (1)

Nimna Perera
Nimna Perera

Reputation: 1065

You need to have a separate state to include all the like states in the numberOfPosts array.

  1. Add a state to hold likes.
const [likes, setLikes] = useState([]);
  1. Add a useEffect to change the array length of like state when array is expanding in infinite scroll
useEffect(() => {
    setLikes(numberOfPosts.map((_, i) => (likes[i] === undefined ? false : likes[i])));
}, [numberOfPosts])
  1. Add a function to change the like state in the particular index.
const handleLike = (index) => {
    setLikes(likes.map((val, i) => index === i ? !val : val));
}
  1. Change the handle like function in the button.
{numberOfPosts.map((key, i) => {
    ...
    <IconButton onClick={() => handleLike(i)} ... >{likes[i] && mouseOver ? <HeartBrokenIcon style={{color: 'red'}}/> : likes[i] ? <FavoriteIcon style={{color: 'red'}} /> : <FavoriteBorderTwoToneIcon /> }</IconButton>
    ...
}

Upvotes: 1

Related Questions