skip to Main Content

I built a star component (used material UI component) based on the mapped object, but the star rating shows the same value when I click on any of them. How can I make each star rating have its own value based on the selection? I want each star section to show its own value.

code preview

import * as React from "react";
import Rating from "@mui/material/Rating";
import Box from "@mui/material/Box";
import "./styles.css";

const data = [
  {
    id: 1,
    label: "Do you like"
  },
  {
    id: 2,
    label: "How do you use"
  },
  {
    id: 3,
    label: "Do you dislike"
  }
];

export default function HoverRating() {
  const [value, setValue] = React.useState(2);

  return (
    <Box sx={{ width: 200, alignItems: "center" }}>
      {data.map((rate, id) => ( 
        <div>
          <p>{rate.label}</p>
          <div className="rating">
            <Rating
              value = {rate.value}
              max = {10}
              onChange = {(event, newValue) => {
                setValue(newValue);
              }}
            />
            <p>{value}</p>
          </div>
        </div>
      ))}
    </Box>
  );
}

link on codesandbox

2

Answers


  1. create a resusable component

    import * as React from "react";
    import Rating from "@mui/material/Rating";
    import Box from "@mui/material/Box";
    import "./styles.css";
    
    const data = [
      {
        id: 1,
        label: "Do you like"
      },
      {
        id: 2,
        label: "How do you use"
      },
      {
        id: 3,
        label: "Do you dislike"
      }
    ];
    
    export default function HoverRating() {
    
    
      return (
        <Box
          sx={{
            width: 200,
            alignItems: "center"
          }}
        >
          {data.map((rate, id) => (
            <RatingComponent rate={rate}/>
           
          ))}
        </Box>
      );
    }
    
    function RatingComponent ({rate}) {
    
      const [value, setValue] = React.useState(2);
    
      return (
        <div>
        <p>{rate.label}</p>
        <div className="rating">
          {" "}
          <Rating
            value={rate.value}
            max={10}
            onChange={(event, newValue) => {
              setValue(newValue);
            }}
          />
          <p>{value} </p>
        </div>
      </div>
      )
    }
    
    Login or Signup to reply.
  2. Instead of storing only a single "global" rating value, store the data array into state and selectively update the appropriate rating object.

    Example:

    const data = [
      {
        id: 1,
        label: "Do you like",
        rating: 0
      },
      {
        id: 2,
        label: "How do you use",
        rating: 0
      },
      {
        id: 3,
        label: "Do you dislike",
        rating: 0
      }
    ];
    
    export default function HoverRating() {
      const [ratings, setRatings] = React.useState(data);
    
      return (
        <Box
          sx={{
            width: 200,
            alignItems: "center"
          }}
        >
          {ratings.map((rate, index) => (
            <div>
              <p>{rate.label}</p>
    
              <div className="rating">
                <Rating
                  value={rate.value}
                  max={10}
                  onChange={(event, rating) => {
                    // shallow copy array and update specific index
                    setRatings((ratings) => ratings.with(index, { ...rate, rating }));
                  }}
                />
                <p>{rate.rating}</p>
              </div>
            </div>
          ))}
        </Box>
      );
    }
    

    Edit creating-different-state-value-for-mapped-object

    enter image description here

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