antonyCas
antonyCas

Reputation: 81

Star Rating Component in react

I am new to react and have started following through the book learning react by Alex Banks and Eve Porcello. I have got to a section that creates a star rating system but at the moment I cant get it working can anyone tell me why? As far as I can tell I have copied the code correctly and everything looks like it should work as intended. Here is the code I have:

  const Star = ({ selected=false, onClick=f=>f }) =>
    <div className={ (selected) ? "star selected" : "star" } onClick={onClick}>
    </div>

Star.propTypes = {
    selected: PropTypes.bool,
    onClick: PropTypes.func
}

class StarRating extends React.Component {
    constructor(props) {
        super(props)
        this.state = { starsSelected: 0 }
        this.change = this.change.bind(this)
    }


    change(starsSelected) {
        this.setState({ starsSelected: starsSelected })
    }

    render() {
        const { totalStars } = this.props
        const { starsSelected } = this.state

        return(
            <div className="star-rating">
                {[...Array(totalStars)].map((n,i) => 
                    <Star 
                        key={i}
                        selected={i<starsSelected}
                        onClick={() => this.change(i+1)}
                    />
                 )}
                <p>{starsSelected} of {totalStars} stars</p>
            </div>
        )
    }
}

StarRating.propTypes = {
    totalStars: PropTypes.number
}

StarRating.defaultProps = {
    totalStars: 5
}

When inspecting the components in react-dev-tools it seems that the stars selected prop is always set to false and I cant figure out why. Thanks for any help anyone can offer

Upvotes: 1

Views: 6100

Answers (5)

Bhadresh Arya
Bhadresh Arya

Reputation: 811


import { FaStar } from "react-icons/fa";

const CreateArray = (length) => [...Array(length)]; // This will create Array with the length provided.

// Star Component
function Star({ selected = false, onSelect }) {
  return (
    <FaStar color={selected ? "orange" : "lightgray"} onClick={onSelect} />
  );
}

// Star Rating component
function StarRating({ totalStars = 5 }) {
  const [selectedStars, setSelectedStars] = useState(0);
  return (
    <>
      {CreateArray(totalStars).map((n, i) => (
        <Star
          key={i}
          selected={selectedStars > i}
          onSelect={() => setSelectedStars(i + 1)}
        />
      ))}
      <p>
        {selectedStars} of {totalStars} // To display selected stars out of total stars
      </p>
    </>
  );
}

function App() {
  return <StarRating totalStars={5} />; // This will display 5 stars
}

Working example - Star Rating - CodeSandbox

Upvotes: 0

TrickOrTreat
TrickOrTreat

Reputation: 911

Inject : npm i star-based-rating directly.

For Reference on this react package: star-based-rating

Upvotes: 0

Ravi Patel
Ravi Patel

Reputation: 169

Your code is working absolutely fine. Check out this link : https://codesandbox.io/s/01wqmzrpjl

Make sure while declaring css classes star is above selected else it will not show the selected style fields if it has same style-field in star className.

Example in my link if I declare selected class above star class then red background (selected style property) is override by grey background (star style property).

Upvotes: -1

Rahul Gandhi
Rahul Gandhi

Reputation: 1095

The code shared is perfectly fine. Just render something from this code on which the click event would be fired.

 const Star = ({ selected=false, onClick=f=>f }) =>
    <div className={ (selected) ? "star selected" : "star" } onClick={onClick}>
    // Something to render maybe?
    </div>

Upvotes: 1

NickHTTPS
NickHTTPS

Reputation: 799

It can be 2 things:

this line: {[...Array(totalStars)].map((n,i) => You need to pass totalStars as a Number and not a string:

<StarRating totalStars={5} />

or

you are not display anything in your Star component. Try this:

const Star = ({ selected = false, onClick = f => f }) => (
  <div className={selected ? "star selected" : "star"} onClick={onClick}>
    Star
  </div>
);

See a working example:

https://codesandbox.io/s/52ox6wmwwk

Upvotes: 1

Related Questions