React Star Widget - 为啥所有星星都在单击时更新?

Posted

技术标签:

【中文标题】React Star Widget - 为啥所有星星都在单击时更新?【英文标题】:React Star Widget - why do all stars update on single click?React Star Widget - 为什么所有星星都在单击时更新? 【发布时间】:2021-08-18 23:54:27 【问题描述】:

我正在尝试创建一个星形小部件。我对每颗星星都有一个状态数组,但是当我单击其中一颗星星时,所有星星都会将自己设置为该状态。我对此很迷茫,请停下来。我添加了很多调试日志。在我设置 newStars[i] = currentStar; 的那一刻,整个 newStars 数组都会更新,但我不明白为什么。

另外,这里是代码笔链接:https://codepen.io/trismi/pen/zYZpvQq?editors=1111

html

<div id="root">
  
</div>

CSS(加上 codepen 中链接的很棒的字体样式表)

.star 
  display: inline-block;
  width: 30px;
  text-align: center;
  color: #ddd;
  font-size: 20px;
  transform: scale(.8);
  transition: transform 50ms ease; 

  &:hover,
  &.semi-active 
    color: gold;
    transform: scale(1);
  
  
  &.selected 
    color: orange;
    transform: scale(1);
  

javascript

function Star(props) 
  console.log(props);
  console.log(props.index);
  let classes = 'star' + (props.selected ? ' selected' : '') + (props.hover ? ' semi-active' : '');
  return (
    <div className=classes onClick=props.onClick>
      <i className="fas fa-star"></i>
    </div>
  );


class RatingWidget extends React.Component 
  constructor(props)
    super(props);
    this.state = 
      stars: Array(5).fill(
        selected: false,
        hover: false,
      ),
    
  

  handleClick(currentStar, index) 
    console.log('\n\n\n******CLICK');
    console.log("star state on click", currentStar);
    console.log("index", index);
    
    let newStars = this.state.stars.slice();
    let newStar = newStars[index];
    console.log("new star ", newStar);
    newStar.selected = !newStar.selected;
    
    newStars[index] = newStar;

    console.log("stars", newStars);

    this.setState(
      stars: newStars
    );
  

  render() 
    let stars = this.state.stars.map((rating, index) => 
      return (
        <Star 
          key=index
          index=index
          onClick=() => this.handleClick(rating, index)
          selected=rating.selected
          hover=rating.hover
        />);
    );

    return (
      <div className="RatingWidget">
        Future rating widget
        stars
      </div>
    );    
  


ReactDOM.render(<RatingWidget />, document.getElementById('root'));

【问题讨论】:

【参考方案1】:

问题出在这里:

Array(5).fill(
    selected: false,
     hover: false,
)

您正在为数组的每个元素填充相同的对象(相同的引用)。

尝试使用:

Array(5).fill(null).map(() => (
         selected: false,
         hover: false,
))

或者使用 Array.from():

Array.from(length: 5, () => ( selected: false, hover: false))

【讨论】:

非常感谢!这让我发疯了。现在开始处理悬停的东西:D【参考方案2】:

你可以有下面的handleClick功能

I updated let newStar = newStars[index]; to let newStar = ...newStars[index];

handleClick(currentStar, index) 
    console.log('\n\n\n******CLICK');
    console.log("star state on click", currentStar);
    console.log("index", index);
    
    let newStars = this.state.stars.slice();
    let newStar = ...newStars[index];
    console.log("new star ", newStar);
    newStar.selected = !newStar.selected;
    
    newStars[index] = newStar;

    console.log("stars", newStars);

    this.setState(
      stars: newStars
    );
  

【讨论】:

以上是关于React Star Widget - 为啥所有星星都在单击时更新?的主要内容,如果未能解决你的问题,请参考以下文章

GitHub 五万星登顶,程序员命令行最全技巧宝典!

为啥星表包含零歌曲,而这里更多?

评级不选择超过 3 星 - React Native Elements - 评级)

这个GitHub项目,5天狂揽2500星登顶GitHub热榜

网友质疑雷军,为啥不买鸿星尔克?

为啥 React 需要这么多 node_modules?如何限制加载所有这些文件以使其值得使用 React?