skip to Main Content

I’m getting data from a payload which has a total number of likes on each post. On the user screen, there’s an icon for the user to like a post and what i want to achieve is when the user taps on it, the value show be increased to plus 1 against that particular post

VIEW:

{
  posts.map((item, i) => {
    return (
      <View key={i} style={styles.user}>
        <Card>

          <ListItem
            titleStyle={{ color: '#36c', fontWeight:'500' }}
            titleNumberOfLines={2}
            hideChevron={false}
            roundAvatar
            title={item.headline}
            avatar={{uri:'https://s3.amazonaws.com/uifaces/faces/twitter/brynn/128.jpg'}}
          />

          <Text style={{marginBottom: 10, fontSize:16, color:'#4a4a4a', fontFamily:'HelveticaNeue-Light'}}>
            {item.text}
          </Text>

          <TouchableOpacity style={styles.likeContainer}>
            <Text style={{fontSize:14}}>{item.likesCount}{"n"}</Text>
            <Icon
              onPress={()=>onLikePost(item)}
              name='md-thumbs-up'
              type='ionicon'
              iconStyle={[(item.isLiked=== true) ? styles.likedColor : styles.unLikedColor]}
            />
          </TouchableOpacity>
        </Card>
      </View>
    );
  })
}

CONTAINER:

state = {
  posts : [],
  id: '',
  user: ''
}

componentDidMount = () => {
  const { navigation } = this.props;
  this.setState({
    id : navigation.getParam('id'), 
    user: navigation.getParam('user')
  }, ()=> this.getData())
}

getData = () => {
  const api = create({
    baseURL: 'https://url.com/api',
    headers: {'Accept': 'application/json'}
  });
  api.get('/groups/'+`${this.state.groupID}`+'/posts').then((response) => {
    let data = response.data.data
    this.setState({ posts: data });
    console.log(JSON.stringify(this.state.posts))
  })
}

onLikePost = (item) => {
  item.likeCount = item.likeCount+1
}

2

Answers


  1. You are storing posts data in state variable so use setState to update it. Use map and check for each post, whenever id (unique property of each post) matches to id of the clicked item, increase its likesCount otherwise return the same data.

    Write it like this:

    onLikePost = (item) => {
      this.setState(prevState => ({
        posts: prevState.posts.map(el => el.id === item.id? {...el, likesCount: el.likesCount+1} : el)
      }))
    }
    

    Update: Put the check before updating the count value and change the isLiked bool also.

    onLikePost = (item) => {
      this.setState(prevState => ({
        posts: prevState.posts.map(el => {
          if(el.id === item.id) {
            return {
              ...el,
              isLiked: !el.isLiked,
              likesCount: !el.isLiked? el.likesCount+1 : el.likesCount-1,
            }
          }
          return el;
        })
      }))
    }
    

    Note: I am assuming each post has a key id unique value, if it doesn’t exist then use any other unique property of the each post.

    Login or Signup to reply.
  2. If array sequence is not an issue, you can use item index and use setState to update it.

    <Icon
      onPress={()=>onLikePost(i)}
      ...
    />
    
    ...
    
    onLikePost = (i) => {
      let posts = this.state.posts;
      posts[i].likesCount = !posts[i].isLiked ? posts[i].likesCount + 1 : posts[i].likesCount - 1;
      posts[i].isLiked = !posts[i].isLiked;
      this.setState({ posts: posts}) 
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search