0

I have very simple forum with React and firebase and currently everyone is allowed to vote on a post, but the problem is you can click on the like and dislike button more than once.

How do i prevent this? I'm trying to do something with location.storage but not sure how to track each post.

class App extends React.Component {
  downvotePost(key, text, vote) {
    // alert(id);
    // CommentsRef.child(id).transaction(function(Comments) {
    //   if (Comments) {
    //     Comments.vote++;
    //   }
    //  console.log('cc',Comments);
    //   return Comments;
    // });

    vote--;
    CommentsRef.child(key).update({ vote: vote });
  }

  upvotePost(key, text, vote) {
    // alert(id);
    // CommentsRef.child(id).transaction(function(Comments) {
    //   if (Comments) {
    //     Comments.vote++;
    //   }
    //  console.log('cc',Comments);
    //   return Comments;
    // });

    vote++;
    CommentsRef.child(key).update({ vote: vote });
  }

  componentWillMount() {
    const { dispatch, match } = this.props;
    dispatch(getsinglechamp(this.props.id));
    console.log(this.props);
  }

  componentDidMount() {
    const hasVisitedBefore = localStorage.getItem("hasVisitedBefore");

    // Check if the user has visited the site (component) before.
    if (!hasVisitedBefore) {
      // If not, set the component state (or dispatch an action if you need)
      // Also set the localStorage so it's globally accessible.
      this.setState({ hasVisitedBefore: false });
      localStorage.setItem("hasVisitedBefore", true);
    }
  }

  render() {
    const { dispatch, loading } = this.props;
    const { comments, ChampsLoading } = this.state;
    const orderedchamps = comments;

    let commentList;

    if (ChampsLoading) {
      commentList = <div className="TaskList-empty">Loading...</div>;
    } else if (comments.length) {
      commentList = (
        <ul className="TaskList">
          {comments.map(comment => (
            <div className="row">
              <div className="col-lg-6">
                <br /> <br /> <br />
                <div className="cs-counter-tips-list">
                  <div className="cs-counter-tip">
                    {this.state.hasVisitedBefore
                      ? "you can vote on this post"
                      : "disable button if user voted"}
                    <button
                      id="f"
                      onClick={() =>
                        this.upvotePost(comment.key, comment.text, comment.vote)
                      }
                    >
                      <Icon icon={chevronUp} />
                    </button>
                    <div id="col" className="col-lg-6">
                      {comment.vote}
                    </div>
                    <button
                      id="f"
                      onClick={() =>
                        this.downvotePost(
                          comment.key,
                          comment.text,
                          comment.vote
                        )
                      }
                    >
                      <Icon icon={chevronDown} />
                    </button>
                    <div>
                      <p className="cs-counter-tip-text">{comment.text} </p>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          ))}
        </ul>
      );
    }
    return (
      <div className="container">
        <h1>Counter Tips</h1>

        <div className="brace"> </div>

        <p> {commentList} </p>
      </div>
    );
  }
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Leo Bogod
  • 369
  • 8
  • 28

1 Answers1

1

There are quite a few things missing here:

  1. You will need to keep track of who already voted. This is typically done with a list like:

    posts
      post1id
        voteCount: 2
        voters
          voter1uid: true
          voter2uid: true
      post2id
        voteCount: 2
        voters
          voter1uid: true
          voter3uid: true
    
  2. You will need to use a transaction to update the vote, and the voters in one go. A Firebase Database transaction allows you to determine the new value of voteCount based on its current value safely, event when multiple people are casting votes around the same time.

  3. You will need to write security rules (which are enforced by the Firebase Database server) to ensure that code can only change voteCount in a way that corresponds to the change in voters. See my answer here for more on that: Is the way the Firebase database quickstart handles counts secure?
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • what if i want non registrated users to be able to upvote also? any way to achieve this using cookies? – Leo Bogod Aug 14 '18 at 15:49
  • You'll need a way to identify users. The easiest way to do that is by using Firebase's anonymous authentication. See https://firebase.google.com/docs/auth/web/anonymous-auth – Frank van Puffelen Aug 14 '18 at 21:51