Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

97
Views
React Function Component doesn't update view onClick

I'm new to React. I have a rating component that I created. The problem I'm having is onClick I can see the rating is updating in the console, but on the page I don't see the change happening. My understanding is that React components need to be pure functions and it's better to prefer functional components over classes. When I try to use the useState hook my rating is added to the previous state and doesn't update correctly on the page.

My first question is what is the best/preferred way to update state within a component? If I'm using a functional component do I have to use a hook?

Please see my code below

export default function Rating(props) {
    let stars = [];
    // const [stars, setStars] = useState([]);
    let star = '☆';

    for (let i = 0; i < props.stars; i++) {
        stars.push(star);
    }

    function rate(index) {
        let filledStar = '★'
        let stars = [];
        // setStars([])


        for (let i = 0; i < props.stars; i++) {
            stars.push(star);
        }
        stars.forEach((star, i) => {
            while (index >= 0) {
                stars[index] = filledStar;
                index--;
            }

        })
        console.log('stars filled', stars)
        return stars

     }

    return (
        <>
        <div className="stars">
            {stars.map((star, i) => (
                <h2 
                    key={i}
                    onClick={() => rate(i)}>{star}
                </h2>
            ))}
        </div>

        </>

    )

}

If I click the fourth star this is returned as expected, but the UI doesn't update

If I click the fourth star this is returned as expected, but the UI doesn't update.

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

Here's a working version that fills in stars up to and including the star that was clicked on - using useState, and useEffect.

const { Fragment, useEffect, useState } = React;

function Rating(props) {

  // Set state as an empty array
  const [stars, setStars] = useState([]);

  // Called by useEffect his function
  // creates a new array of empty stars
  function initStars() {
    const stars = [];
    for (let i = 0; i < +props.stars; i++) {
      stars.push('☆');
    }
    setStars(stars);
  }

  // Called when the component
  // first mounts, and called only once
  useEffect(() => {
    initStars();
  }, []);

  function rate(e) {

    // Get the id from the star dataset
    const { id } = e.target.dataset;

    // Create a fresh array
    const stars = [];

    // Loop; if the current index is less or
    // equal to the id set it as a filled star
    // otherwise set it to an empty star
    for (let i = 0; i < +props.stars; i++) {
      stars.push(i <= +id ? '★' : '☆');
    }

    // Set the state with the new array
    setStars(stars);

  }

  return (
    <div>
      {stars.map((star, i) => (
        <span
          className="star"
          key={i}
          data-id={i}
          onClick={rate}
        >{star}
        </span>
      ))}
    </div>
  );

};

ReactDOM.render(
  <Rating stars="10" />,
  document.getElementById('react')
);
.star { font-size: 1.8em; }
.star:hover { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

about 4 years ago · Juan Pablo Isaza Report

0

So, it seems that I need to use the useState hook. I'm sure there is another way to do this, but this worked for me.

 export default function Rating(props) {
        const [stars, setStars] = useState([]);
        let star = '☆';

        function initStars() {
            const stars = [];
            for (let i = 0; i < props.stars; i++) {
               stars.push(star);
            }
            setStars(stars);
        }

        // Called when the component
        // first mounts, and called only once
        useEffect(() => {
            initStars();
        }, []);

        function rate(index) {
            console.log('index', index);
            let filledStar = '★'
            let stars = [];

            console.log('setStars', stars);

            for (let i = 0; i < props.stars; i++) {
               stars.push(star);
            }
            stars.forEach((star, i) => {
                while (index >= 0) {
                   stars[index] = filledStar;
                   index--;
                }

            })
            console.log('stars filled', stars)
            // return stars
            setStars(stars)

         }

         // console.log('stars', stars);

        return (
        <>
            <div className="stars">
                {stars.map((star, i) => (
                    <h2 
                        key={i}
                        onClick={() => rate(i)}>
                        {star}
                    </h2>
                ))}
            </div>

        </>

    )

}
about 4 years ago · Juan Pablo Isaza Report

0

As you suggested, you will need to use hooks in order to seek the functionality you're looking for (or use a class component). In your current implementation, you're not actually using React states, so React doesn't know that you want it to re-render your component. Also, the stars array you're using in rate() is different from the stars array in your component. You don't seem to be making use of the stars array created and returned by rate()

How exactly have you tried to use useState?

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!