1

I have the following code to render 5 stars for a component. I want it always to be exactly 5 stars, but depending on the rating, the rest of the stars should be blank. I have the following code to achieve this.:

const stars = []
for (let i = 0; i < 5; i++){
  if (i < Math.floor(rating)){
    stars.push(<span className="feedback-star full"></span>)
  } else {
    stars.push(<span className="feedback-star blank"></span>)
  }
}

React is saying that I should have a unique key prop for each span. How should achieve this effectively? (I guess I could use new Date(), or Math.random(), but won't it be a lot of unnecessary operations on a list of over 100 feedbacks, each 5 stars?)

Balázs Orbán
  • 559
  • 1
  • 4
  • 26
  • 1
    just add something like `key={"star"+i}` should be good enough – A. L Sep 09 '17 at 11:28
  • Even enough with only i. I don't know why I thought that the entire thing is one big Array..! It is only 5 elements in every little array. Thanks! – Balázs Orbán Sep 09 '17 at 11:32

1 Answers1

3

You read up on keys in React and how to use them efficiently. You might find this post useful. Basically:

React uses the key prop to understand the component-to-DOM Element relation which is then used for the reconciliation process. It is therefore very important that the key always remains unique, otherwise there is a good chance React will mix up the elements and mutate the incorrect one.


That being said, to solve your problem, try this:

let stars = []
for (let i = 0; i < 5; i++){
  if (i < Math.floor(rating)){
    stars.push(<span key={i} className="feedback-star full"></span>)
  } else {
    stars.push(<span key={i} className="feedback-star blank"></span>)
  }
}

For a shorter syntax, you could also do:

let stars = []
for (let i = 0; i < 5; i++){
  stars.push(<span key={i} className={"feedback-star " + (i < Math.floor(rating) ?  "full" : "blank")}></span>)
}

Also note that with const you are creating a read-only reference to a variable and must not mutate it. For this scenario, use let instead.

Chris
  • 57,622
  • 19
  • 111
  • 137
  • Great answer. Just a side note, I believe using just indexes for key is not a good idea. something like `key={'start'+i}` would be a better use. – bennygenel Sep 09 '17 at 11:35
  • @bennygenel, I don't think that wouldn't make any difference whatsoever. – Chris Sep 09 '17 at 11:36
  • In this case I believe you are right. I just wanted show a representation of a unique key. – bennygenel Sep 09 '17 at 11:38
  • @bennygenel, yeah, keys only need to be unique **among their siblings**, not globally. See https://facebook.github.io/react/docs/lists-and-keys.html#keys-must-only-be-unique-among-siblings – Chris Sep 09 '17 at 11:39
  • Not a good use case but what about using 2 for loops one after the other rendering same components? Do they count as siblings? – bennygenel Sep 09 '17 at 11:48
  • @bennygenel yes, if they have the same parent. – Chris Sep 09 '17 at 11:49
  • That why I think giving a unique addition for each loop or map is a good idea. It was just just a personal note. – bennygenel Sep 09 '17 at 11:53