Is there a way I can make this code shorter?

Viewed 100

So I have a rating system and I have made the following code for showing how many stars to show, although it is very long winded and so I am trying to work out a way to make it much shorter.

I dunno if there's some kind of algorithm to multiply and then add the empty star or something?

const rating = (recipe) => {
    const value = (recipe.rating / recipe.votes.length).toFixed(1);
    if (value >= 4.9)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaStar />
          <FaStar />
          <FaStar />
        </>
      );
    if (value >= 4.5)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaStar />
          <FaStar />
          <FaStarHalfAlt />
        </>
      );
    if (value >= 4)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaStar />
          <FaStar />
          <FaRegStar />
        </>
      );
    if (value >= 3.5)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaStar />
          <FaStarHalfAlt />
          <FaRegStar />
        </>
      );
    if (value >= 3)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaStar />
          <FaRegStar />
          <FaRegStar />
        </>
      );
    if (value >= 2.5)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaStarHalfAlt />
          <FaRegStar />
          <FaRegStar />
        </>
      );
    if (value >= 2)
      return (
        <>
          <FaStar />
          <FaStar />
          <FaRegStar />
          <FaRegStar />
          <FaRegStar />
        </>
      );
    if (value >= 1.5)
      return (
        <>
          <FaStar />
          <FaStarHalfAlt />
          <FaRegStar />
          <FaRegStar />
          <FaRegStar />
        </>
      );
    if (value >= 1)
      return (
        <>
          <FaStar />
          <FaRegStar />
          <FaRegStar />
          <FaRegStar />
          <FaRegStar />
        </>
      );
    if (value >= 0.5)
      return (
        <>
          <FaStarHalfAlt />
          <FaRegStar />
          <FaRegStar />
          <FaRegStar />
          <FaRegStar />
        </>
      );
    return (
      <>
        <FaRegStar />
        <FaRegStar />
        <FaRegStar />
        <FaRegStar />
        <FaRegStar />
      </>
    );
  };
2 Answers

If you want to really make it short:

const rating = (recipe) => {
    const value = (recipe.rating / recipe.votes.length).toFixed(1);

    const stars = Array.from(Array(5)).map(() => <FaRegStar/>);

    if (value >= 4.9) {
        return stars.map(() => <FaStar/>);
    }

    for (let i = 0; i < Math.round(value); i++) {
        stars[i] = i > value - 1 ? <FaStarHalfAt/> : <FaStar/>;
    }

    return stars;
};

This would be a bit easier to understand (this will show 5 stars when rating >= 4.9):

const rating = (recipe) => {
    let value = (recipe.rating / recipe.votes.length).toFixed(1);

    if (value >= 4.9) {
        return Array.from(Array(5)).map(() => <FaStar/>);
    }

    const stars = [];
    while (value >= 1) {
        stars.push(<FaStar/>);
        value--;
    }

    if (value >= 0.5) {
        stars.push(<FaStarHalfAt/>);
    }

    while (stars.length < 5) {
        stars.push(<FaRegStar/>);
    }

    return stars;
};

Or a bit shorter but still understandable:

const rating = (recipe) => {
    let value = (recipe.rating / recipe.votes.length).toFixed(1);
    
    if (value >= 4.9) {
        return Array.from(Array(5)).map(() => <FaStar/>);
    }

    const stars = [];
    while (stars.length < 5) {
        stars.push(value >= 1
            ? <FaStar/>
            : value >= 0.5
                ? <FaStarHalfAt/>
                : <FaRegStar/>);
        value--;
    }

    return stars;
};

I had to make a similar module for myself and that's the way I wrote it:

let rating = 4.5 // your rating

const html = []

for (let i = 0; i < 5; i++) { // 5 total stars
    if (rating >= 1) {
        html.push(<FullStar />)
        rating--
    } else if (rating > 0) {
        html.push(<HalfStar />)
        rating--
    } else {
        html.push(<EmptyStar />)
    }
}

return html // html that contains all 5 stars

If you ever need to repeat yourself multiple times use for loop, hope this helps :)

Related