0

I have built a minimal ReactJS component to update the number of likes. All works well but the count does not update when clicked. I tried following several answers but cannot figure out why.

See the code:

import React, {useState} from 'react';

class GiveLikes extends React.Component {
  // set the initial value of the likes
  state = {likes:0};

  // Function is called every time "likes" is clicked
  likes_count = (likes) =>{
    // Counter state is incremented
    this.state({likes: likes+1});
    }
    
  render() {
    return (
      <>
      <h2> {this.state.likes} </h2>
      <div className="buttons">
        <button style={{
        fontSize: '60%',
        position: 'relative',
        top: '20vh',
        marginRight: '5px',
        backgroundColor: 'green',
        borderRadius: '8%',
        color: 'white',
        }}
        onClick={() => this.likes_count}>Likes
        </button>
      </div>  
    </>

    )

    }
  }
  
export default GiveLikes;

The above code will render the following on the web browser. Clicking the "Likes" should update the value of the count, but unfortunately it does not.

Rendered Image of the ReactJS component.

1
  • try changing this.state({likes: likes+1}); to this.setState({likes: likes+1}); also initiliaze your state in a constructor Commented Sep 10, 2021 at 19:30

4 Answers 4

3
  1. Declare a constructor and initialize your state,
  2. Use an arrow function on your likes_count() method
  3. Use this.setState({likes: this.state.likes +1}); instead of this.state({likes: this.state.likes +1});
import React, {useState} from 'react';
class GiveLikes extends React.Component {

constructor(props) {
  super(props);
  this.state = {likes: 0};
}

likes_count = () => {
    this.setState({likes: this.state.likes +1});
}

render() {
    return (
    <>
    <h2> {this.state.likes} </h2>
    <div className="buttons">
      <button style={{
        fontSize: '60%',
        position: 'relative',
        top: '20vh',
        marginRight: '5px',
        backgroundColor: 'green',
        borderRadius: '8%',
        color: 'white',
        }}
        onClick={this.likes_count}>Likes
      </button>
    </div>  
    </>
    )
  }
}
export default GiveLikes;
Sign up to request clarification or add additional context in comments.

Comments

0

Edit:

The summary of this answer is that the state does not exist because there is no constructor for this.state

I believe the answer to be is Props are never to be updated. We are to use them as is. Sounds rigid right? But React has its reasons behind this rule and I’m pretty convinced by their reasoning. The only caveat is, though, that there are situations where we might need to initiate the update of a prop. And we will soon know how.

Consider the following line of code from a parent component:

<MyChild childName={this.state.parentName} />

Now if there is any change of name required, parentName will be changed in the parent and that change will automatically be communicated to the child as is the case with the React mechanism. This setup works in most of the scenarios.

But what if you need to update the prop of the child component, and the knowledge of the change required and the trigger to change it is only known to the child? Considering the ways of React, data can only flow from top-to-bottom i.e., from parent-to-child. So then how are we to communicate to the parent that a change to prop is required?

Answer from the following source: https://www.freecodecamp.org/news/how-to-update-a-components-prop-in-react-js-oh-yes-it-s-possible-f9d26f1c4c6d/

I've only shown the parts you need to read nothing else. Please analyse your code properly next time, this isn't a hard thing to do .

Comments

0

You forgot to call the function -

onClick={() => this.likes_count()}

Also, Instead of passing likes you need to use the data from state and then update it like -

    likes_count = () => {
    let likes = this.state.likes;
    this.setState({ likes: likes + 1 });
    };

Comments

0

Add a constructor and initialize this.state otherwise it won't be exists.

What happens is every time you re-render your component (by state or props change) you will re-create the your state again and again with {likes: 0} and it will not work.

Also, you are mixing class component and functional component syntax style, which will lead to more bugs and issues with react and your code.

Moreover, you need to put a function that will be called in onClick but you created a function that returns a function, and it is wrong in your case.

Another issue is to set your likes state using this.setState and not just calling state as a function.

import React from 'react';

class GiveLikes extends React.Component {

  constructor(props) {
    super(props);
    this.state = {likes: 0};
  }

  likes_count = () => {
    this.setState ({likes: this.state.likes +1});
  }
    
    render() {
      return (
        <>
        <h2> {this.state.likes} </h2>
        <div className="buttons">
          <button style={{
          fontSize: '60%',
          position: 'relative',
          top: '20vh',
          marginRight: '5px',
          backgroundColor: 'green',
          borderRadius: '8%',
          color: 'white',
          }}
          onClick={this.likes_count}>Likes
          </button>
        </div>  
      </>

      )

    }
}

export default GiveLikes;

Read about react.

Focus on your first component (look for examples with counters components online).

Don't rush into things without fully understand. React is fun.

12 Comments

Probably don't have to delcare constructor, see the class field proposal: github.com/tc39/proposal-class-fields
@Omri I did try to put a function for clicking outside the scope of the class, but it was a little confusing when trying to call it from within the class.
@everestial007 it should be inside the class, just like I did here :)
@OmriAttiya Also note that you have to use arrow function for likes_count or manually bind "this", other wise the code won't work
@Limboer your comment helped.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.