1

I am using WebSockets to update upvotes on comments in React. I am receiving comment updates in logs of different client instances. However, React does not render the updates to upvotes.

Code I am trying:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';

class Comment extends Component {

    constructor(props){
      super(props);
      this.upvotes = React.createRef();
      this.downvotes = React.createRef();
      this.handleUpvote = this.handleUpvote.bind(this);
      this.handleDownvote = this.handleDownvote.bind(this);

    }

    handleUpvote(){
      console.log(this.props);
      const json = { type: 'upvote' };
      json.data = this.props;
      json.data.comment.upvotes++;
      console.log(json);
      this.props.socket.send(JSON.stringify(json));

    }

    handleDownvote(){
      this.downvotes.current.innerHTML++;
      console.log(this.downvotes.current.innerHTML);

    }
    render() {
      return (  
      <tr>
        <td>{this.props.comment.user.firstName} {this.props.comment.user.lastName}</td>
        <td>{this.props.comment.content }</td>
        <td> <span ref={this.upvotes}>{this.props.comment.upvotes}</span> <button onClick={this.handleUpvote}>Upvote</button> </td>
        <td> <span ref={this.downvotes}>{this.props.comment.downvotes}</span>  <button onClick={this.handleDownvote}>Downvote</button> </td>
      </tr>
    )

    }

}

export default class ListComments extends Component {

  constructor(props){
    super(props);
    this.state = { comments: [] }
  }

  componentDidMount(){
    axios.get('http://localhost:5000/api/comments/')
      .then(resp => this.setState({ comments : resp.data }))
      .catch(err => console.log(err));
  }

  componentWillReceiveProps(nextProps){

    const data = JSON.parse(nextProps.comment);
    console.log(data.data);
    if(data.type === "upvote"){
      // const a = this.state.comments;
      // a.forEach(comment => {
      //   if(comment._id == data.data.comment._id){
      //     comment = data.data.comment
      //   }
      // });
      // this.setState({ comments : a })
      this.setState(prevState => { 

        // Get previous state
        const { comments }  = prevState;

        // Add new item to array
        comments.forEach(comm => {
          if(comm._id == data.data.comment._id){
            comm = data.data.comment
          }
        });

        // Return new state 
        return { comments };
    });
    }
    else if(data.type === "comment"){
      this.setState({ comments : [data.data, ...this.state.comments] })
    }
  }

  commentList() {
    return this.state.comments.map(currentcomment => {
      return <Comment comment={currentcomment} socket={this.props.actions} key={currentcomment._id}/>;
    })
  }
  render() {
    return (
      <div>
      <h3>Comments</h3>
      <table className="table">
          <thead className="thead-light">
            <tr>
              <th>Username</th>
              <th>Content</th>
              <th>Upvotes</th>
              <th>Downvotes</th>
            </tr>
          </thead>
          <tbody>
            { this.commentList() }
          </tbody>
        </table>
      </div>
    );
  }
}

Outputs I am getting - Client one with 3 upvotes to question 1 Client one with 3 upvotes to question 1

Client 2 with updates to upvotes received in console, not rendred in actual comment Client 2 with updates to upvotes received in console, not rendred in actual comment

Sairaj Sawant
  • 1,842
  • 1
  • 12
  • 16
  • I'm not 100% sure, but it looks like you have a nested state. Changing the value of `this.state.comments.upvotes` will not cause a re-render. React doesn't look at deep objects. Maybe try adding `this.state.upvotes` or look here: https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react – sallf Oct 01 '19 at 04:21
  • Thanks for the reply! I will try that one! – Sairaj Sawant Oct 01 '19 at 04:45
  • That did work! Thanks! – Sairaj Sawant Oct 02 '19 at 05:58

0 Answers0