【问题标题】: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'));

【问题讨论】:

    标签: reactjs widget rating


    【解决方案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
        });
      }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 2014-05-14
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 2021-09-21
      相关资源
      最近更新 更多