简体   繁体   中英

how to trigger re-render of rating component

I am trying out React for first time. I have taken a problem to try building a 5-star rating component. It prints all logs properly. Just that the component is not re-rendering when state is changed. Appreciate your time reading this. Here is JSFiddle version of the problem.

HTML:

<div id="app"></div>

CSS:

span {
  margin: 10px;
  font-size:25px;
}

span.active {
  color:red;
}

JS:

class RatingApp extends React.Component {

    constructor(props) {
    super(props)
    
    this.state = {
        rating : 0,
        items: [
            {id:1, active: false },
            {id:2, active: false },
            {id:3, active: false },
            {id:4, active: false },
            {id:5, active: false }
        ]
    }
}

toggleClass(itemId) {

    console.log("itemId ----" + itemId);

    var changedItems = this.state.items;
    console.log("id ----" + changedItems[itemId-1].id);
    console.log("active ----" + changedItems[itemId-1].active);
    console.log("pre changedItems ---- " + changedItems);
    for(var i=1; i<=5; i++) {
        if(i<=itemId) {
            changedItems[i-1].active = true;
            console.log("active class added");
        }
        else {
            changedItems[i-1].active = false;
        }
    }
    console.log("post changedItems ---- " + changedItems);
    this.setState=({
        rating: itemId,
        items: changedItems
    });
};

render() {
    return (
      <div id="rating">
   
        {this.state.items.map(item => (
        <span key={item.id} className={item.active ? "active" : ""}
            onClick={() => this.toggleClass(item.id)} 
        >
           *
        </span>
        ))}
     
      </div>
    )
  }
}

ReactDOM.render(<RatingApp />, document.querySelector("#app"))

remove the = after this.setState

The first issue is this part

this.setState=({
        rating: itemId,
        items: changedItems
    });

it should be

this.setState({
        rating: itemId,
        items: changedItems
    });

The error is in

this.setState=({ rating: itemId, items: changedItems })

change it to this.setState({ rating: itemId, items: changedItems })

Refer below

 class RatingApp extends React.Component { constructor(props) { super(props) this.state = { rating: 0, items: [ {id:1, active: false }, {id:2, active: false }, {id:3, active: false }, {id:4, active: false }, {id:5, active: false } ] } } toggleClass(itemId) { console.log("itemId ----" + itemId); var changedItems = this.state.items; console.log("id ----" + changedItems[itemId-1].id); console.log("active ----" + changedItems[itemId-1].active); console.log("pre changedItems ---- " + changedItems); for(var i=1; i<=5; i++) { if(i<=itemId) { changedItems[i-1].active = true; console.log("active class added"); } else { changedItems[i-1].active = false; } } console.log("post changedItems ---- " + changedItems); /* this.setState=({ rating: itemId, items: changedItems }); */ this.setState({ rating: itemId, items: changedItems }); }; render() { return ( <div id="rating"> {this.state.items.map(item => ( <span key={item.id} className={item.active? "active": ""} onClick={() => this.toggleClass(item.id)} > * </span> ))} </div> ) } } ReactDOM.render(<RatingApp />, document.querySelector("#app"))
 span { margin: 10px; font-size:25px; } span.active { color:red; }
 <:doctype html> <html lang="en"> <head> <meta charset="utf-8"> <script src="https.//cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min:js"></script> <script src="https.//cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> </head> <body> <div id="app"></div> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM