patrick
patrick

Reputation: 353

React Star Rating Component

I've created a simple star rating component to make users able to review my books.

Here's the component:

import React, { useState } from 'react'
import { FaStar } from 'react-icons/fa'

const StarRating = (props) => {
    const [rating, setRating] = useState(null);

    return (
        <Wrapper>
            {[...Array(5)].map((star, i) => {
                const ratingValue = i + 0;
                return (
                    <label>
                        <input
                            type="radio"
                            name="rating"
                            onClick={() => setRating(props.ratingValue)}
                        />
                        <FaStar color={ratingValue < rating ? "#01af93" : "#bbb"} />
                    </label>
                )
            })}
        </Wrapper>
    )
}

export default StarRating

So, if somebody clicks on the Stars the rating will appear (using an onClick handler).

I would like to display the ratings without the onClick handler now.

I've tried simply to add value={props.ratingValue} instead of onClick={() => setRating(props.ratingValue)} but it doesn't work.

Hope someone can help with what I'm doing wrong.

Upvotes: 0

Views: 2513

Answers (2)

ND verma
ND verma

Reputation: 297

work for me try this

import React, { useState } from 'react';
    import { View, Text, TouchableOpacity } from 'react-native';
    import Icon from 'react-native-vector-icons/FontAwesome';
    
    const RatingStar = () => {
      const [rating, setRating] = useState(0);
    
      const handleRatingPress = (selectedRating) => {
        setRating(selectedRating);
      };
    
      const renderStars = () => {
        const stars = [];
        const totalStars = 5;
    
        for (let i = 1; i <= totalStars; i++) {
          const starIconName =
            i <= rating
              ? 'star'
              : i - rating <= 0.5
              ? 'star-half-o'
              : 'star-o';
    
          stars.push(
            <TouchableOpacity
              key={i}
              onPress={() => handleRatingPress(i)}
            >
              <Icon name={starIconName} size={30} color="#FFD700" />
            </TouchableOpacity>
          );
        }
    
        return stars;
      };
    
      return (
        <View style={{ alignItems: 'center' }}>
          <Text style={{ fontSize: 20, marginBottom: 10 }}>
            Rating: {rating.toFixed(1)}
          </Text>
          <View style={{ flexDirection: 'row' }}>{renderStars()}</View>
        </View>
      );
    };
    
    export default RatingStar;

Upvotes: 0

chety
chety

Reputation: 156

You have to move onClick handler and value to the parent container class. So changing state and keeping current input value must be done in your parent container. Below I share a code snippet for your sample.

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

const StarRating = (props) => {
  console.log(props);
  return (
    <div>
      {Array(5)
        .fill(0)
        .map((_, idx) => (
          <label key={idx}>
            <input
              type="radio"
              name="rating"
              onChange={() => props.setRating(idx)}
              value={props.ratingValue}
              checked={idx === props.ratingValue}
            />
            <FaStar color={idx < 3 ? "#01af93" : "#bbb"} />
          </label>
        ))}
    </div>
  );
};

export const RatingContainer = () => {
  const [rate, setRate] = useState(3);

  return (
    <div>
      <StarRating setRating={(val) => setRate(val)} ratingValue={rate} />
    </div>
  );
};

Upvotes: 2

Related Questions