skip to Main Content

I have a recipe app and i implemented a star rating, i have to save the value in local storage and display the average rating value.I updated the code after reading the answers in order to get the recipe id and the rating in the local storage and it kinda works.Using console log i was able to see that the rating and the id showing good but nothing is saving in the local storage and i don’t understand why any help?

This is the code:

import styled from "styled-components";
import Searched from "../Pages/Searched";
import { useParams } from "react-router-dom";
const StarRating = () => {
  

  let params = useParams();
  const [details, setDetails] = useState({});
  const [activeTab, setActiveTab] = useState("instructions");
  
  const fetchDetails = async () => {
      const data = await fetch(
      `https://api.spoonacular.com/recipes/${params.name}/information?apiKey=${process.env.REACT_APP_API_KEY}`
      );
      const detailData = await data.json();
      setDetails(detailData);
      console.log(detailData);
  };

  useEffect(() => {
      fetchDetails();
  }, [params.name]);

    const [rating, setRating] = useState(0);
    const [hover, setHover] = useState(0);

    useCallback(() => {
      const data = localStorage.getItem("rating");
      if (data) {
        data[details.id] = rating;
        localStorage.setItem("rating", JSON.stringify(data));
      } else {
        localStorage.setItem("rating", JSON.stringify({ [details.id]: rating }));
      }
    }, [rating]);
    
    
    return (
        <StarStyle>
      <div className="star-rating">
        {[...Array(5)].map((star, index) => {
          index += 1;
          return (
            <button
              type="button"
              key={index}
              className={index <= (hover || rating) ? "on" : "off"}
              onClick={() => setRating(index)}
              onMouseEnter={() => setHover(index)}
              onMouseLeave={() => setHover(rating)}
            >
              <span className="star">★</span>
            </button>
          );
        })}
      </div>
      </StarStyle>
    );
  };


export default StarRating;

const StarStyle = styled.form`
button {
    background-color: transparent;
    border: none;
    outline: none;
    cursor: pointer;
    block-size: 150px;
    font-size: 60px;
  }
  .on {
    color: #000;
  }
  .off {
    color: #ccc;
  }
`;

2

Answers


  1. You can use a useEffect hook that watches for the change of the rating and set it in the localStorage.

    For example you need to do something like the following:

    import React, { useState, useCallback } from "react";
    import styled from "styled-components";
    
      const StarRating = () => {
      const [rating, setRating] = useState(0);
      const [hover, setHover] = useState(0);
    
      useCallback(() => {
        localStorage.setItem("rating", JSON.stringify(rating));
      }, [rating]);
    
      return (
        <StarStyle>
          <div className="star-rating">
            {[...Array(5)].map((star, index) => {
              index += 1;
              return (
                <button
                  type="button"
                  key={index}
                  className={index <= (hover || rating) ? "on" : "off"}
                  onClick={() => setRating(index)}
                  onMouseEnter={() => setHover(index)}
                  onMouseLeave={() => setHover(rating)}
                >
                  <span className="star">&#9733;</span>
                </button>
              );
            })}
          </div>
      </StarStyle>
      );
    };
    
    export default StarRating;
    

    This is a simple implementation that sets the value of the rating to the localStorage whenever the rating state changes.

    In real life, you will need to save the product ID with the rating, so in case you have multiple products, you can display the correct rating. I would suggest you pass the productId to the component as a prob then set an object with all the ratings you have in the localStorage where you use the product ID as a key.

    That would be something like that:

      const StarRating = (productId) => {
    
      ...
    
      useCallback(() => {
        const data = localStorage.getItem("rating");
        if (data) {
          data[productId] = rating;
          localStorage.setItem("rating", JSON.stringify(data));
        } else {
          localStorage.setItem("rating", JSON.stringify({ [productId]: rating }));
        }
      }, [rating]);
    
    ...
    
    

    As you can see, we are passing the product ID as a prob to the component then in the hook we look for the previously stored data in the local storage.

    If it exist, we update the data. If not we create a new object that stores the data.

    Login or Signup to reply.
  2. First of all make a component for Rating in React js
    and follow this code :

    import React, { useState } from "react";
    import "./StarRating.css";
    
    const StarRating = () => {
    
    
    
    const [rating, setRating] = useState(0);
      const [hover, setHover] = useState(0);
      return (
        <div className="star-rating">
          {[...Array(5)].map((star, index) => {
            index += 1;
            return (
              <button
                type="button"
                key={index}
                className={index <= (hover || rating) ? "on" : "off"}
                onClick={() => setRating(index)}
                onMouseEnter={() => setHover(index)}
                onMouseLeave={() => setHover(rating)}
              >
                <span className="star fs-2">&#9733;</span>
              </button>
            );
          })}
        </div>
      );
    };
    
    export default StarRating;
    

    and make css file and write this code

    button {
      background-color: transparent;
      border: none;
      outline: none;
      cursor: pointer;
    }
    .on {
      color: #ffd900;
    }
    .off {
      color: #ffd90073;
    }
    

    and use it anywhere

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search