合并状态以获取评分成分

时间:2020-07-14 10:33:36

标签: javascript reactjs typescript react-native react-hooks

我正在尝试制作星级评分。我正在使用三元运算符来检查状态是否为真。如果是,我使用黄色的星星或白色的星星。但是,这看起来像是不好的代码实践。代替重复所有这些三元运算符,是否有可能以某种方式组合条件并仅渲染状态为真的那些黄色星星?

const [oneStar, setOneStar] = useState(false);
const [twoStar, setTwoStar] = useState(false);
const [threeStar, setThreeStar] = useState(false);
const [fourStar, setFourStar] = useState(false);
const [fiveStar, setFiveStar] = useState(false);

const ratings = [
    1,2,3,4,5
]

const setRating = (rating: number) => {
  console.log('rating', rating);
  if(rating == 1){
      setOneStar(true);
      setTwoStar(false);
      setThreeStar(false);
      setFourStar(false);
      setFiveStar(false);
  }
  if(rating == 2){
    setOneStar(true);
    setTwoStar(true);
    setThreeStar(false);
    setFourStar(false);
    setFiveStar(false);
}
if(rating == 3){
    setOneStar(true);
    setTwoStar(true);
    setThreeStar(true);
    setFourStar(false);
    setFiveStar(false);
}
if(rating == 4){
    setOneStar(true);
    setTwoStar(true);
    setThreeStar(true);
    setFourStar(true);
    setFiveStar(false);
}
if(rating == 5){
    setOneStar(true);
    setTwoStar(true);
    setThreeStar(true);
    setFourStar(true);
    setFiveStar(true);
}
};

return (
<View style={styles.ratingContainer}>
    <TouchableOpacity onPress={() => setRating(1)}>
        {oneStar ? 
      <Icon name= "star" color='#ebba34' size={moderateScale(13)} /> : <Icon name= "star-o" size={moderateScale(13)} />}
    </TouchableOpacity>
    <TouchableOpacity onPress={() => setRating(2)}>
        {twoStar ? 
      <Icon name= "star" color='#ebba34' size={moderateScale(13)} /> : <Icon name= "star-o" size={moderateScale(13)} />}
    </TouchableOpacity>
    <TouchableOpacity onPress={() => setRating(3)}>
        {threeStar ? 
      <Icon name= "star" color='#ebba34' size={moderateScale(13)} /> : <Icon name= "star-o" size={moderateScale(13)} />}
    </TouchableOpacity>
    <TouchableOpacity onPress={() => setRating(4)}>
        {fourStar ? 
      <Icon name= "star" color='#ebba34' size={moderateScale(13)} /> : <Icon name= "star-o" size={moderateScale(13)} />}
    </TouchableOpacity>
    <TouchableOpacity onPress={() => setRating(5)}>
        {fiveStar ? 
      <Icon name= "star" color='#ebba34' size={moderateScale(13)} /> : <Icon name= "star-o" size={moderateScale(13)} />}
    </TouchableOpacity>
</View>
);
};

4 个答案:

答案 0 :(得分:1)

类似这样的东西:

const [stars, setStars] = useState(1);

...        

{
  [1, 2, 3, 4, 5].map((x, i) => (
    <TouchableOpacity onPress={() => setStars(i)}>
      {stars <= i ? (
        <Icon name="star" color="#ebba34" size={moderateScale(13)} />
      ) : (
        <Icon name="star-o" size={moderateScale(13)} />
      )}
    </TouchableOpacity>
  ));
}

答案 1 :(得分:0)

您可以为此使用数字

const [stars, setStars] = useState(0);

,然后仅使用此setStars方法。无需setRating和所有重复步骤

   <TouchableOpacity onPress={() => setStars(1)}>
        {stars <= 1 ? 
      <Icon name= "star" color='#ebba34' size={moderateScale(13)} /> : <Icon name= "star-o" size={moderateScale(13)} />}
    </TouchableOpacity>

答案 2 :(得分:0)

一种解决方法是,仅当用户单击特定的恒星时,跟踪“选择”了多少颗恒星。

function Rating() {
  const [stars, setStars] = React.useState(0);
  const ratings = [1, 2, 3, 4, 5];

  return (
    <View style={styles.ratingContainer}>
      {/* Iterate through all `ratings` and render stars for each */}
      {ratings.map(rating => (
        <TouchableOpacity key={rating} onPress={() => setStars(rating)}>
          {/* If `stars` is not 0 and `rating` is less than or equal 
              to the number of `stars`, then show a selected star */}
          {stars !== 0 && rating <= stars ? (
            <Icon name="star" color="#ebba34" size={moderateScale(13)} />
          ) : (
            <Icon name="star-d" size={moderateScale(13)} />
          )}
        </TouchableOpacity>
      ))}
    </View>
  );
}

这是一个例子:

答案 3 :(得分:0)

const Rating = () => {
  const [currentRating, setRating] = useState(0);

  const styles = rating => {
    return {
      width: "20px",
      height: "20px",
      border: "1px solid",
      backgroundColor: stars >= rating ? "green" : "red"
    };
  };

  const rates = [1, 2, 3, 4, 5];

  const stars = rates.map(rate => {
    return currentRating >= rate ? (
      <TouchableOpacity onPress={() => setRating(rate)}>
        <Icon name="star" color="#ebba34" size={moderateScale(13)} />
      </TouchableOpacity>
    ) : (
      <TouchableOpacity onPress={() => setRating(rate)}>
        <Icon name="star-o" size={moderateScale(13)} />
      </TouchableOpacity>
    );
  });

  return <View>{stars}</View>;